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