Initial revision
[OpenSRF.git] / src / libtransport / transport_socket.c
1 #include "transport_socket.h"
2
3
4 /*
5 int main( char* argc, char** argv ) {
6
7         transport_socket sock_obj;
8         sock_obj.port = 5222;
9         sock_obj.server = "10.0.0.4";
10         sock_obj.data_received_callback = &print_stuff;
11
12         printf("connecting...\n");
13         if( (tcp_connect( &sock_obj )) < 0 ) {
14                 printf( "error connecting" );
15         }
16
17         printf("sending...\n");
18         if( tcp_send( &sock_obj, "<stream>\n" ) < 0 ) {
19                 printf( "error sending" );
20         }
21         
22         printf("waiting...\n");
23         if( tcp_wait( &sock_obj, 15 ) < 0 ) {
24                 printf( "error receiving" );
25         }
26
27         printf("disconnecting...\n");
28         tcp_disconnect( &sock_obj );
29
30 }
31 */
32
33
34 // returns the socket fd, -1 on error
35 int tcp_connect( transport_socket* sock_obj ){
36
37         if( sock_obj == NULL ) {
38                 fatal_handler( "connect(): null sock_obj" );
39                 return -1;
40         }
41         struct sockaddr_in remoteAddr, localAddr;
42         struct hostent *hptr;
43         int sock_fd;
44
45         #ifdef WIN32
46         WSADATA data;
47         char bfr;
48         if( WSAStartup(MAKEWORD(1,1), &data) ) {
49                 fatal_handler( "somethin's broke with windows socket startup" );
50                 return -1;
51         }
52         #endif
53
54
55
56         // ------------------------------------------------------------------
57         // Create the socket
58         // ------------------------------------------------------------------
59         if( (sock_fd = socket( AF_INET, SOCK_STREAM, 0 )) < 0 ) {
60                 fatal_handler( "tcp_connect(): Cannot create socket" );
61                 return -1;
62         }
63
64         // ------------------------------------------------------------------
65         // Get the hostname
66         // ------------------------------------------------------------------
67         if( (hptr = gethostbyname( sock_obj->server ) ) == NULL ) {
68                 fatal_handler( "tcp_connect(): Unknown Host" );
69                 return -1;
70         }
71
72         // ------------------------------------------------------------------
73         // Construct server info struct
74         // ------------------------------------------------------------------
75         memset( &remoteAddr, 0, sizeof(remoteAddr));
76         remoteAddr.sin_family = AF_INET;
77         remoteAddr.sin_port = htons( sock_obj->port );
78         memcpy( (char*) &remoteAddr.sin_addr.s_addr,
79                         hptr->h_addr_list[0], hptr->h_length );
80
81         // ------------------------------------------------------------------
82         // Construct local info struct
83         // ------------------------------------------------------------------
84         memset( &localAddr, 0, sizeof( localAddr ) );
85         localAddr.sin_family = AF_INET;
86         localAddr.sin_addr.s_addr = htonl( INADDR_ANY );
87         localAddr.sin_port = htons(0);
88
89         // ------------------------------------------------------------------
90         // Bind to a local port
91         // ------------------------------------------------------------------
92         if( bind( sock_fd, (struct sockaddr *) &localAddr, sizeof( localAddr ) ) < 0 ) {
93                 fatal_handler( "tcp_connect(): Cannot bind to local port" );
94                 return -1;
95         }
96
97         // ------------------------------------------------------------------
98         // Connect to server
99         // ------------------------------------------------------------------
100         if( connect( sock_fd, (struct sockaddr*) &remoteAddr, sizeof( struct sockaddr_in ) ) < 0 ) {
101                 fatal_handler( "tcp_connect(): Cannot connect to server %s", sock_obj->server );
102                 return -1;
103         }
104
105         sock_obj->sock_fd = sock_fd;
106         sock_obj->connected = 1;
107         return sock_fd;
108
109 }
110
111
112 int tcp_send( transport_socket* sock_obj, const char* data ){
113
114         if( sock_obj == NULL ) {
115                 fatal_handler( "tcp_send(): null sock_obj" );
116                 return 0;
117         }
118
119         //fprintf( stderr, "TCP Sending: \n%s\n", data );
120
121         // ------------------------------------------------------------------
122         // Send the data down the TCP pipe
123         // ------------------------------------------------------------------
124         if( send( sock_obj->sock_fd, data, strlen(data), 0 ) < 0 ) {
125                 fatal_handler( "tcp_send(): Error sending data" );
126                 return 0;
127         }
128         return 1;
129 }
130
131
132 int tcp_disconnect( transport_socket* sock_obj ){
133
134         if( sock_obj == NULL ) {
135                 fatal_handler( "tcp_disconnect(): null sock_obj" );
136                 return -1;
137         }
138
139         if( close( sock_obj->sock_fd ) == -1 ) {
140
141                 // ------------------------------------------------------------------
142                 // Not really worth throwing an exception for... should be logged.
143                 // ------------------------------------------------------------------
144                 warning_handler( "tcp_disconnect(): Error closing socket" );
145                 return -1;
146         } 
147
148         return 0;
149 }
150
151 // ------------------------------------------------------------------
152 // And now for the gory C socket code.
153 // Returns 0 on failure, 1 otherwise
154 // ------------------------------------------------------------------
155 int tcp_wait( transport_socket* sock_obj, int timeout ){
156
157         if( sock_obj == NULL ) {
158                 fatal_handler( "tcp_wait(): null sock_obj" );
159                 return 0;
160         }
161
162         int n = 0; 
163         int retval = 0;
164         char buf[BUFSIZE];
165         int sock_fd = sock_obj->sock_fd;
166
167
168         fd_set read_set;
169
170         FD_ZERO( &read_set );
171         FD_SET( sock_fd, &read_set );
172
173         // ------------------------------------------------------------------
174         // Build the timeval struct
175         // ------------------------------------------------------------------
176         struct timeval tv;
177         tv.tv_sec = timeout;
178         tv.tv_usec = 0;
179
180         if( timeout == -1 ) {  
181
182                 // ------------------------------------------------------------------
183                 // If timeout is -1, there is no timeout passed to the call to select
184                 // ------------------------------------------------------------------
185                 if( (retval = select( sock_fd + 1 , &read_set, NULL, NULL, NULL)) == -1 ) {
186                         warning_handler( "Call to select failed" );
187                         return 0;
188                 }
189
190         } else if( timeout != 0 ) { /* timeout of 0 means don't block */
191
192                 if( (retval = select( sock_fd + 1 , &read_set, NULL, NULL, &tv)) == -1 ) {
193                         warning_handler( "Call to select failed" );
194                         return 0;
195                 }
196         }
197
198         memset( &buf, 0, BUFSIZE );
199
200         if( set_fl( sock_fd, O_NONBLOCK ) < 0 ) 
201                 return 0;
202
203 #ifdef _ROUTER // just read one buffer full of data
204
205         n = recv(sock_fd, buf, BUFSIZE-1, 0);
206         sock_obj->data_received_callback( sock_obj->user_data, buf );
207         if( n == 0 )
208                 n = -1;
209
210 #else // read everything we can
211
212         while( (n = recv(sock_fd, buf, BUFSIZE-1, 0) ) > 0 ) {
213                 //printf("\nReceived:  %s\n", buf);
214                 sock_obj->data_received_callback( sock_obj->user_data, buf );
215                 memset( &buf, 0, BUFSIZE );
216         }
217
218 #endif
219
220         if( clr_fl( sock_fd, O_NONBLOCK ) < 0 ) {
221                 return 0;
222         }
223
224         if( n < 0 ) { 
225                 if( errno != EAGAIN ) { 
226                         warning_handler( " * Error reading socket with errno %d", errno );
227                         return 0;
228                 }
229         }
230
231 #ifdef _ROUTER
232         return n;
233 #else
234         return 1;
235 #endif
236
237 }
238
239 int set_fl( int fd, int flags ) {
240         
241         int val;
242
243         if( (val = fcntl( fd, F_GETFL, 0) ) < 0 ) {
244                 fatal_handler("fcntl F_GETFL error");
245                 return -1;
246         }
247
248         val |= flags;
249
250         if( fcntl( fd, F_SETFL, val ) < 0 ) {
251                 fatal_handler( "fcntl F_SETFL error" );
252                 return -1;
253         }
254         return 0;
255 }
256         
257 int clr_fl( int fd, int flags ) {
258         
259         int val;
260
261         if( (val = fcntl( fd, F_GETFL, 0) ) < 0 ) {
262                 fatal_handler("fcntl F_GETFL error" );
263                 return -1;
264         }
265
266         val &= ~flags;
267
268         if( fcntl( fd, F_SETFL, val ) < 0 ) {
269                 fatal_handler( "fcntl F_SETFL error" );
270                 return -1;
271         }
272         return 0;
273 }
274         
275
276 /*
277 int tcp_connected( transport_socket* obj ) {
278
279         int ret;
280         if( ! obj->sock_fd ) { return 0; }
281
282         ret = read( obj->sock_fd  , NULL,0 );
283         if( ret <= 0 ) {
284                 return 0;
285         }
286         return 1;
287 }
288 */
289