rdmtest.c
6.54 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
/*----------------------------------------------------------------
* rdmtest.c - RDM test program for Libnet
*----------------------------------------------------------------
* libnet is (c) Copyright Chad Catlett and George Foot 1997-1999
*
* Please look in `docs' for details, documentation and
* distribution conditions.
*/
/* Based on gentest. */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#if defined TARGET_MSVC || defined TARGET_MINGW32
#include <windows.h>
#define sleep(x) Sleep ((x)*1000)
#else
#include <unistd.h>
#endif
#include <libnet.h>
#define SIZE 70
/* list_drivers:
* Displays a list of the drivers in the given list.
*/
void list_drivers (NET_DRIVERNAME *drvs, char *title) {
printf ("\nDriver list: %s\n", title);
while (drvs->name) {
printf ("\t%d\t%s\n", drvs->num, drvs->name);
drvs++;
}
printf ("\n");
}
/* in_list:
* Checks whether driver `x' is in list `drvs'.
*/
int in_list (NET_DRIVERNAME *drvs, int x) {
while (drvs->name) {
if (x == drvs->num) return 1;
drvs++;
}
return 0;
}
/* get_and_init_driver:
* Gets some driver lists from the library, asks the user to choose a driver,
* and then initialises that driver.
*/
int get_and_init_driver (void)
{
NET_DRIVERNAME *drivers;
NET_DRIVERLIST avail;
int choice;
char buffer[16];
printf ("Getting driver names...\n");
drivers = net_getdrivernames (net_drivers_all);
list_drivers (drivers, "All drivers");
free (drivers);
printf ("Detecting available drivers...\n");
avail = net_detectdrivers (net_drivers_all);
printf ("Getting detected driver names...\n");
drivers = net_getdrivernames (avail);
do {
list_drivers (drivers, "Available drivers");
printf ("Please choose a driver from the above list.\n");
fgets (buffer, 10, stdin);
choice = atoi (buffer);
} while (!in_list (drivers, choice));
free (drivers);
avail = net_driverlist_create();
net_driverlist_add (avail, choice);
if (!net_initdrivers (avail)) {
printf("Error initialising driver.\n");
exit (1);
}
return choice;
}
/* server_startup:
* Startup routine for the server. It opens a conn, listens for connections,
* and opens another conn when it gets a connection.
*/
void server_startup (int driver, NET_CONN **conn, NET_CONN **conn2)
{
if (!(*conn2 = net_openconn (driver, ""))) {
printf("Couldn't open conn.\n");
exit (2);
}
printf ("Listening");
fflush (stdout);
if (!net_listen (*conn2)) {
do {
putchar ('.');
fflush (stdout);
sleep (1);
*conn = net_poll_listen (*conn2);
} while (!*conn);
if (!*conn) {
puts ("User aborted.");
exit (3);
}
} else {
puts ("Error occured.");
exit (3);
}
}
/* callback used by `client_startup' below */
int callback (void)
{
putchar ('.');
fflush (stdout);
return 0;
}
/* client_startup:
* Startup routine for the client. It opens a conn and connects it to the
* server.
*/
void client_startup (int driver, NET_CONN **conn, char *target)
{
int x;
if (!(*conn = net_openconn (driver, NULL))) {
printf("Couldn't open conn.\n");
exit (2);
}
printf ("Connecting");
fflush (stdout);
x = net_connect_wait_cb (*conn, target, callback);
if (x) {
if (x > 0)
puts ("User aborted.");
else
puts ("Error occured.");
net_closeconn (*conn);
exit(3);
}
}
int main (void) {
NET_CONN *conn, *conn2 = NULL;
char buffer[SIZE];
char target[1024];
int client, driver;
net_init();
net_loadconfig (NULL);
driver = get_and_init_driver();
puts ("Enter target address (blank to be server):\n");
fgets (target, 1024, stdin);
{ char *ch = strchr (target, '\n'); if (ch) *ch = '\0'; }
client = !!target[0];
/* This program is basically peer-to-peer; the only difference between client
* and server is in the connection protocol. So here we call the appropriate
* connection routine; after this, the client and server are connected and
* both use the same code to communicate.
*/
if (!client)
server_startup (driver, &conn, &conn2);
else
client_startup (driver, &conn, target);
puts ("Connection established.\n");
puts ("Now type lines of text, which will be sent through the connection.");
puts ("Incoming data will be checked for after each line.");
puts ("Type a line empty except for a full stop to quit.\n");
printf ("The maximum line length is just over %d characters.\n\n", SIZE-5);
do {
/* If we're serving, check whether the client is still trying to connect.
* This might seem a bit odd; it's here in case our acknowledgement of
* their attempt does not get through. The library will resend the ack if
* the same client tries to connect again; we don't need to catch the
* returned conn because we don't really care what it is.
*
* If we were planning to serve to more than one client, with clients able
* to connect at any time, we'd have a different system here; see the
* rdmchat example program.
*/
if (!client) net_poll_listen (conn2);
/* This is the receive loop. We check whether messages are waiting, and if
* there are any we process them. We are wide open to flooding here -- in
* practice it might be better to restrict the number of messages we
* process each cycle.
*/
while (net_query_rdm (conn)) {
int x;
x = net_receive_rdm (conn, buffer, SIZE - 1);
if (x == -1) {
puts ("[recv failure]");
} else {
buffer[x] = 0;
printf ("recv: %s\n", buffer);
}
}
/* This demonstrates the net_conn_stats function -- it gets the number of
* incoming packets waiting to be read and the number of unacknowledged
* outgoing packets. Probably not particularly useful in practice, but you
* might be able to optimise your networking system using this information.
*/
{
int in_q, out_q;
net_conn_stats (conn, &in_q, &out_q);
printf ("(%d:%d) ", in_q, out_q);
}
/* Get input and send it. This blocks, of course, so you won't see
* incoming data until you hit Enter.
*/
{
char *chptr;
printf ("send: ");
fgets (buffer, SIZE - 5, stdin);
chptr = strchr (buffer, '\0');
if (*(chptr-1) == '\n') *--chptr = 0;
if (chptr != buffer) {
int x;
x = net_send_rdm (conn, buffer, chptr - buffer);
if (x) puts ("[send failure]");
}
}
} while (strcmp (buffer,"."));
puts ("Quitting...");
net_closeconn (conn);
if (!client) net_closeconn (conn2);
return 0;
}