xref: /reactos/modules/rostests/tests/tcpsvr/tcpsvr.c (revision 845faec4)
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 	closesocket(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 
176