Patch by Jonathon Wilson:
[reactos.git] / reactos / apps / tests / tcpsvr / tcpsvr.c
1 /* tcpServer.c
2 *
3 * Simple Winsock TCP server test.
4 * Later will be used as base for ReactOS telnetd
5 *
6 * HISTORY:
7 * 6-15-02 - Added Winsock support to UNIX tcp test
8 * 6-16-02 - Removed Unix support
9 * 6-17-02 - Added extra comments to code
10 *
11 */
12
13 #include <winsock2.h>
14 #include <stdio.h>
15 #include <string.h>
16 #include <io.h>
17
18 #undef ERROR
19 #define SUCCESS 0
20 #define ERROR 1
21
22 #define END_LINE 0x0A
23 #define SERVER_PORT 23
24 #define MAX_MSG 100
25
26 /* function readline */
27 int read_line();
28
29 int main (int argc, char *argv[]) {
30
31 WORD wVersionRequested;
32 WSADATA WsaData;
33 INT Status;
34 int sd, newSd, cliLen;
35
36 struct sockaddr_in cliAddr, servAddr;
37 char line[MAX_MSG];
38
39 wVersionRequested = MAKEWORD(2, 2);
40
41 Status = WSAStartup(wVersionRequested, &WsaData);
42 if (Status != 0) {
43 printf("Could not initialize winsock dll.\n");
44 return FALSE;
45 }
46
47 /* create socket */
48 sd = socket(AF_INET, SOCK_STREAM, 0);
49 if(sd<0) {
50 perror("cannot open socket ");
51 WSACleanup();
52 return ERROR;
53 }
54
55 /* bind server port */
56 servAddr.sin_family = AF_INET;
57 servAddr.sin_addr.s_addr = htonl(INADDR_ANY);
58 servAddr.sin_port = htons(SERVER_PORT);
59
60 if(bind(sd, (struct sockaddr *) &servAddr, sizeof(servAddr))<0) {
61 perror("cannot bind port ");
62 WSACleanup();
63 return ERROR;
64 }
65
66 listen(sd,5);
67
68 while(1) {
69
70 printf("%s: \n"
71 "To start test, Please telnet to localhost (127.0.0.1) port 23 \n"
72 "When connected input raw data followed by End of Line\n"
73 "Test is now running on TCP port %u\n",argv[0],SERVER_PORT);
74
75 cliLen = sizeof(cliAddr);
76 newSd = accept(sd, (struct sockaddr *) &cliAddr, &cliLen);
77 if(newSd<0) {
78 perror("cannot accept connection ");
79 WSACleanup();
80 return ERROR;
81 }
82
83 /* init line */
84 memset(line,0x0,MAX_MSG);
85
86 /* receive segments */
87 while(read_line(newSd,line)!=ERROR) {
88
89 printf("%s: received from %s:TCP%d : %s\n", argv[0],
90 inet_ntoa(cliAddr.sin_addr),
91 ntohs(cliAddr.sin_port), line);
92 /* init line */
93 memset(line,0x0,MAX_MSG);
94
95 } /* while(read_line) */
96
97 } /* while (1) */
98
99 }
100
101
102 /* WARNING WARNING WARNING WARNING WARNING WARNING WARNING */
103 /* this function is experimental.. I don't know yet if it works */
104 /* correctly or not. Use Steven's readline() function to have */
105 /* something robust. */
106 /* WARNING WARNING WARNING WARNING WARNING WARNING WARNING */
107
108 /* rcv_line is my function readline(). Data is read from the socket when */
109 /* needed, but not byte after bytes. All the received data is read. */
110 /* This means only one call to recv(), instead of one call for */
111 /* each received byte. */
112 /* You can set END_CHAR to whatever means endofline for you. (0x0A is \n)*/
113 /* read_lin returns the number of bytes returned in line_to_return */
114 int read_line(int newSd, char *line_to_return) {
115
116 static int rcv_ptr=0;
117 static char rcv_msg[MAX_MSG];
118 static int n;
119 int offset;
120
121 offset=0;
122
123 while(1) {
124 if(rcv_ptr==0) {
125 /* read data from socket */
126 memset(rcv_msg,0x0,MAX_MSG); /* init buffer */
127 n = recv(newSd, rcv_msg, MAX_MSG, 0); /* wait for data */
128 if (n<0) {
129 perror(" cannot receive data ");
130 return ERROR;
131 } else if (n==0) {
132 printf(" connection closed by client\n");
133 close(newSd);
134 WSACleanup();
135 return ERROR;
136 }
137 }
138
139 /* if new data read on socket */
140 /* OR */
141 /* if another line is still in buffer */
142
143 /* copy line into 'line_to_return' */
144 while(*(rcv_msg+rcv_ptr)!=END_LINE && rcv_ptr<n) {
145 memcpy(line_to_return+offset,rcv_msg+rcv_ptr,1);
146 offset++;
147 rcv_ptr++;
148 }
149
150 /* end of line + end of buffer => return line */
151 if(rcv_ptr==n-1) {
152 /* set last byte to END_LINE */
153 *(line_to_return+offset)=END_LINE;
154 rcv_ptr=0;
155 return ++offset;
156 }
157
158 /* end of line but still some data in buffer => return line */
159 if(rcv_ptr <n-1) {
160 /* set last byte to END_LINE */
161 *(line_to_return+offset)=END_LINE;
162 rcv_ptr++;
163 return ++offset;
164 }
165
166 /* end of buffer but line is not ended => */
167 /* wait for more data to arrive on socket */
168 if(rcv_ptr == n) {
169 rcv_ptr = 0;
170 }
171
172 } /* while */
173 }
174
175