Троан Эрик В.
Шрифт:
11: #include <sys/socket.h>
12: #include <unistd.h>
13: #include <fcntl.h>
14:
15: #include "sockutil.h" /* некоторые служебные функции */
16:
17: #define RRQ 1 /* запрос на чтение */
18: #define DATA 3 /* блок данных */
19: #define ACK 4 /* подтверждение */
20: #define ERROR 5 /* возникла ошибка */
21:
22: /* коды ошибок tftp */
23: #define FILE_NOT_FOUND 1
24:
25: struct tftpPacket {
26: short opcode;
27:
28: union {
29: char bytes[514]; /* самый большой блок, который мы
30: можем обработать, содержит 2 байта
31: для номера блока и 512 для данных */
32: struct {
33: short code;
34: char message[200];
35: } error;
36:
37: struct {
38: short block;
39: char bytes[512];
40: } data;
41:
42: struct {
43: short block;
44: } ack;
45: } u;
46: };
47:
48: void sendError(int s, int errorCode) {
49: struct tftpPacket err;
50: int size;
51:
52: err.opcode = htons(ERROR);
53:
54: err.u.error.code = htons(errorCode); /* файл не найден */
55: switch (errorCode) {
56: case FILE_NOT_FOUND:
57: strcpy(err.u.error.message, "файл не найден");
58: break;
59: }
60:
61: /* 2 байта кода операции, 2 байта кода ошибки, сообщение и '\0' */
62: size = 2 + 2 + strlen(err.u.error.message) + 1;
63: if (send(s, &err, size, 0) != size)
64: die("erarorsend");
65: }
66:
67: void handleRequest(struct addrinfo tftpAddr,
68: struct sockaddr remote, int remoteLen,
69: struct tftpPacket request) {
70: char * fileName;
71: char * mode;
72: int fd;
73: int s;
74: int size;
75: int sizeRead;
76: struct tftpPacket data, response;
77: int blockNum = 0;
78:
79: request.opcode = ntohs(request.opcode);
80: if (request.opcode != RRQ) die("неверный код операции");
81:
82: fileName = request.u.bytes;
83: mode = fileName + strlen(fileName) + 1;
84:
85: /* здесь поддерживается только режим bin */
86: if (strcmp(mode, "octet")) {
87: fprintf(stderr, "неверный режим %s\n", mode);
88: exit(1);
89: }
90:
91: /* требуется передача при помощи сокета того же семейства и типа,
92: с которым мы начинали */
93: if ((s = socket(tftpAddr.ai_family, tftpAddr.ai_socktype,
94: tftpAddr.ai_protocol)) < 0)
95: die("send socket");
96:
97: /* установить удаленный конец сокета на адрес, который
98: инициирует данное соединение */
99: if (connect(s, &remote, remoteLen))
100: die("connect");