1#include <stdio.h> 2#include <sys/types.h> 3#include <fcntl.h> 4#include <sys/stat.h> 5#include <inttypes.h> 6#include "pico_stack.h" 7#include "pico_config.h" 8#include "pico_ipv4.h" 9#include "pico_icmp4.h" 10#include "pico_socket.h" 11#include "pico_stack.h" 12#include "pico_device.h" 13#include "pico_dev_vde.h" 14#include "pico_tftp.h" 15 16static struct pico_device *pico_dev; 17 18int32_t get_filesize(const char *filename) 19{ 20 int ret; 21 struct stat buf; 22 23 ret = stat(filename, &buf); 24 if (ret) 25 return -1; 26 27 return buf.st_size; 28} 29 30void start_rx(struct pico_tftp_session *session, int *synchro, const char *filename, int options) 31{ 32 int ret; 33 int fd; 34 int32_t len; 35 uint8_t buf[PICO_TFTP_PAYLOAD_SIZE]; 36 int left = 1000; 37 int countdown = 0; 38 39 printf("Start receiving file %s with options set to %d\n", filename, options); 40 41 if (options) { 42 ret = pico_tftp_set_option(session, PICO_TFTP_OPTION_FILE, 0); 43 if (ret) { 44 fprintf(stderr, "Error in pico_tftp_set_option\n"); 45 exit(1); 46 } 47 } 48 49 ret = pico_tftp_app_start_rx(session, filename); 50 if (ret) { 51 fprintf(stderr, "Error in pico_tftp_app_start_rx\n"); 52 exit(1); 53 } 54 55 fd = open(filename, O_WRONLY | O_EXCL | O_CREAT, 0664); 56 if (!fd) { 57 fprintf(stderr, "Error in open\n"); 58 countdown = 1; 59 } 60 61 for(; left; left -= countdown) { 62 usleep(2000); /* PICO_IDLE(); */ 63 pico_stack_tick(); 64 if (countdown) 65 continue; 66 67 if (*synchro) { 68 len = pico_tftp_get(session, buf, PICO_TFTP_PAYLOAD_SIZE); 69 if (len < 0) { 70 fprintf(stderr, "Failure in pico_tftp_get\n"); 71 close(fd); 72 countdown = 1; 73 continue; 74 } 75 76 ret = write(fd, buf, len); 77 if (ret < 0) { 78 fprintf(stderr, "Error in write\n"); 79 pico_tftp_abort(session, TFTP_ERR_EXCEEDED, "File write error"); 80 close(fd); 81 countdown = 1; 82 continue; 83 } 84 85 printf("Written %" PRId32 " bytes to file (synchro=%d)\n", len, *synchro); 86 87 if (len != PICO_TFTP_PAYLOAD_SIZE) { 88 close(fd); 89 printf("Transfer complete!\n"); 90 countdown = 1; 91 } 92 } 93 } 94} 95 96void start_tx(struct pico_tftp_session *session, int *synchro, const char *filename, int options) 97{ 98 int ret; 99 int fd; 100 int32_t len; 101 uint8_t buf[PICO_TFTP_PAYLOAD_SIZE]; 102 int left = 1000; 103 int countdown = 0; 104 105 printf("Start sending file %s with options set to %d\n", filename, options); 106 107 if (options) { 108 ret = get_filesize(filename); 109 if (ret < 0) { 110 fprintf(stderr, "Error in get_filesize\n"); 111 exit(1); 112 } 113 114 ret = pico_tftp_set_option(session, PICO_TFTP_OPTION_FILE, ret); 115 if (ret) { 116 fprintf(stderr, "Error in pico_tftp_set_option\n"); 117 exit(1); 118 } 119 } 120 121 ret = pico_tftp_app_start_tx(session, filename); 122 if (ret) { 123 fprintf(stderr, "Error in pico_tftp_app_start_rx\n"); 124 exit(1); 125 } 126 127 fd = open(filename, O_RDONLY, 0444); 128 if (!fd) { 129 fprintf(stderr, "Error in open\n"); 130 pico_tftp_abort(session, TFTP_ERR_EACC, "Error opening file"); 131 countdown = 1; 132 } 133 134 for(; left; left -= countdown) { 135 usleep(2000); /* PICO_IDLE(); */ 136 pico_stack_tick(); 137 if (countdown) 138 continue; 139 140 if (*synchro) { 141 ret = read(fd, buf, PICO_TFTP_PAYLOAD_SIZE); 142 if (ret < 0) { 143 fprintf(stderr, "Error in read\n"); 144 pico_tftp_abort(session, TFTP_ERR_EACC, "File read error"); 145 close(fd); 146 countdown = 1; 147 continue; 148 } 149 150 printf("Read %" PRId32 " bytes from file (synchro=%d)\n", len, *synchro); 151 152 len = pico_tftp_put(session, buf, ret); 153 if (len < 0) { 154 fprintf(stderr, "Failure in pico_tftp_put\n"); 155 close(fd); 156 countdown = 1; 157 continue; 158 } 159 160 if (len != PICO_TFTP_PAYLOAD_SIZE) { 161 close(fd); 162 printf("Transfer complete!\n"); 163 countdown = 1; 164 } 165 } 166 } 167} 168 169void usage(const char *text) 170{ 171 fprintf(stderr, "%s\nArguments must be <filename> <mode>\n" 172 "<mode> can be:\n" 173 "\tg => GET request without options\n" 174 "\tG => GET request WITH options\n" 175 "\tp => PUT request without options\n" 176 "\tP => PUT request WITH options\n\n", 177 text); 178 exit(1); 179} 180 181int main(int argc, char**argv) 182{ 183 struct pico_ip4 my_ip; 184 union pico_address server_address; 185 struct pico_ip4 netmask; 186 struct pico_tftp_session *session; 187 int synchro; 188 int options = 0; 189 void (*operation)(struct pico_tftp_session *session, int *synchro, const char *filename, int options); 190 191 unsigned char macaddr[6] = { 192 0, 0, 0, 0xa, 0xb, 0x0 193 }; 194 195 uint16_t *macaddr_low = (uint16_t *) (macaddr + 2); 196 *macaddr_low = *macaddr_low ^ (uint16_t)((uint16_t)getpid() & (uint16_t)0xFFFFU); 197 macaddr[4] ^= (uint8_t)(getpid() >> 8); 198 macaddr[5] ^= (uint8_t) (getpid() & 0xFF); 199 200 pico_string_to_ipv4("10.40.0.10", &my_ip.addr); 201 pico_string_to_ipv4("255.255.255.0", &netmask.addr); 202 pico_string_to_ipv4("10.40.0.2", &server_address.ip4.addr); 203 204 if (argc != 3) { 205 usage("Invalid number or arguments"); 206 } 207 208 switch (argv[2][0]) { 209 case 'G': 210 options = 1; 211 case 'g': 212 operation = start_rx; 213 break; 214 case 'P': 215 options = 1; 216 case 'p': 217 operation = start_tx; 218 break; 219 default: 220 usage("Invalid mode"); 221 } 222 223 printf("%s start!\n", argv[0]); 224 pico_stack_init(); 225 pico_dev = (struct pico_device *) pico_vde_create("/tmp/vde_switch", "tap0", macaddr); 226 227 if(!pico_dev) { 228 fprintf(stderr, "Error creating pico device, got enough privileges? Exiting...\n"); 229 exit(1); 230 } 231 232 pico_ipv4_link_add(pico_dev, my_ip, netmask); 233 printf("Starting picoTCP loop\n"); 234 235 session = pico_tftp_app_setup(&server_address, short_be(PICO_TFTP_PORT), PICO_PROTO_IPV4, &synchro); 236 if (!session) { 237 fprintf(stderr, "Error in pico_tftp_app_setup\n"); 238 exit(1); 239 } 240 241 printf("synchro %d\n", synchro); 242 243 operation(session, &synchro, argv[1], options); 244} 245