00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00028 #include "dnxTcp.h"
00029 #include "dnxTSPI.h"
00030
00031 #include "dnxTransport.h"
00032 #include "dnxError.h"
00033 #include "dnxDebug.h"
00034 #include "dnxLogging.h"
00035
00036 #include <stdio.h>
00037 #include <stdlib.h>
00038 #include <stddef.h>
00039 #include <string.h>
00040 #include <errno.h>
00041 #include <assert.h>
00042 #include <sys/types.h>
00043 #include <sys/time.h>
00044 #include <sys/socket.h>
00045 #include <sys/select.h>
00046 #include <netinet/in.h>
00047 #include <netdb.h>
00048 #include <unistd.h>
00049 #include <pthread.h>
00050 #include <limits.h>
00051
00052 #ifndef HOST_NAME_MAX
00053 # define HOST_NAME_MAX 256
00054 #endif
00055
00057 #define DNX_TCP_LISTEN 5
00058
00060 typedef struct iDnxTcpChannel_
00061 {
00062 char * host;
00063 int port;
00064 int socket;
00065 iDnxChannel ichan;
00066 } iDnxTcpChannel;
00067
00070 static pthread_mutex_t tcpMutex;
00071
00072
00073
00074
00075
00085 static int dnxTcpOpen(iDnxChannel * icp, int mode)
00086 {
00087 iDnxTcpChannel * itcp = (iDnxTcpChannel *)
00088 ((char *)icp - offsetof(iDnxTcpChannel, ichan));
00089 struct hostent * he;
00090 struct sockaddr_in inaddr;
00091 int sd;
00092
00093 assert(icp && itcp->port > 0);
00094
00095 inaddr.sin_family = AF_INET;
00096 inaddr.sin_port = (in_port_t)itcp->port;
00097 inaddr.sin_port = htons(inaddr.sin_port);
00098
00099
00100 if (!strcmp(itcp->host, "INADDR_ANY")
00101 || !strcmp(itcp->host, "0.0.0.0")
00102 || !strcmp(itcp->host, "0"))
00103 {
00104
00105 if (mode == DNX_MODE_ACTIVE) return DNX_ERR_ADDRESS;
00106 inaddr.sin_addr.s_addr = INADDR_ANY;
00107 }
00108 else
00109 {
00110 DNX_PT_MUTEX_LOCK(&tcpMutex);
00111 if ((he = gethostbyname(itcp->host)) != 0)
00112 memcpy(&inaddr.sin_addr.s_addr, he->h_addr_list[0], he->h_length);
00113 DNX_PT_MUTEX_UNLOCK(&tcpMutex);
00114
00115 if (!he) return DNX_ERR_ADDRESS;
00116 }
00117
00118 if ((sd = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP)) < 0)
00119 {
00120 dnxLog("dnxUdpOpen: socket failed: %s.", strerror(errno));
00121 return DNX_ERR_OPEN;
00122 }
00123
00124
00125 if (mode == DNX_MODE_ACTIVE)
00126 {
00127 if (connect(sd, (struct sockaddr *)&inaddr, sizeof inaddr) != 0)
00128 {
00129 close(sd);
00130 dnxLog("dnxTcpOpen: connect(%lx) failed: %s.",
00131 (unsigned long)inaddr.sin_addr.s_addr, strerror(errno));
00132 return DNX_ERR_OPEN;
00133 }
00134 }
00135 else
00136 {
00137
00138 if (bind(sd, (struct sockaddr *)&inaddr, sizeof inaddr) != 0)
00139 {
00140 close(sd);
00141 dnxLog("dnxTcpOpen: bind(%lx) failed: %s.",
00142 (unsigned long)inaddr.sin_addr.s_addr, strerror(errno));
00143 return DNX_ERR_OPEN;
00144 }
00145 listen(sd, DNX_TCP_LISTEN);
00146 }
00147
00148 itcp->socket = sd;
00149
00150 return DNX_OK;
00151 }
00152
00153
00154
00161 static int dnxTcpClose(iDnxChannel * icp)
00162 {
00163 iDnxTcpChannel * itcp = (iDnxTcpChannel *)
00164 ((char *)icp - offsetof(iDnxTcpChannel, ichan));
00165
00166 assert(icp && itcp->socket);
00167
00168 shutdown(itcp->socket, SHUT_RDWR);
00169 close(itcp->socket);
00170 itcp->socket = 0;
00171
00172 return DNX_OK;
00173 }
00174
00175
00176
00193 static int dnxTcpRead(iDnxChannel * icp, char * buf, int * size,
00194 int timeout, char * src)
00195 {
00196 iDnxTcpChannel * itcp = (iDnxTcpChannel *)
00197 ((char *)icp - offsetof(iDnxTcpChannel, ichan));
00198 char mbuf[DNX_MAX_MSG];
00199 unsigned short mlen;
00200
00201 assert(icp && itcp->socket && buf && size && *size > 0);
00202
00203
00204 if (timeout > 0)
00205 {
00206 struct timeval tv;
00207 fd_set fd_rds;
00208 int nsd;
00209
00210 FD_ZERO(&fd_rds);
00211 FD_SET(itcp->socket, &fd_rds);
00212
00213 tv.tv_usec = 0L;
00214 tv.tv_sec = timeout;
00215
00216 if ((nsd = select(itcp->socket + 1, &fd_rds, 0, 0, &tv)) == 0)
00217 return DNX_ERR_TIMEOUT;
00218
00219 if (nsd < 0)
00220 {
00221 if (errno != EINTR)
00222 {
00223 dnxLog("dnxTcpRead: select failed: %s.", strerror(errno));
00224 return DNX_ERR_RECEIVE;
00225 }
00226 return DNX_ERR_TIMEOUT;
00227 }
00228 }
00229
00230
00231 if (read(itcp->socket, &mlen, sizeof mlen) != sizeof mlen)
00232 return DNX_ERR_RECEIVE;
00233 mlen = ntohs(mlen);
00234
00235
00236 if (mlen < 1 || mlen > DNX_MAX_MSG)
00237 return DNX_ERR_RECEIVE;
00238
00239
00240 if (*size >= mlen)
00241 {
00242 if (read(itcp->socket, buf, (int)mlen) != (int)mlen)
00243 return DNX_ERR_RECEIVE;
00244 *size = (int)mlen;
00245 }
00246 else
00247 {
00248 if (read(itcp->socket, mbuf, (int)mlen) != (int)mlen)
00249 return DNX_ERR_RECEIVE;
00250 memcpy(buf, mbuf, *size);
00251 }
00252
00253
00254 if (src)
00255 {
00256 socklen_t slen;
00257 *src = 0;
00258 getpeername(itcp->socket, (struct sockaddr *)src, &slen);
00259 }
00260 return DNX_OK;
00261 }
00262
00263
00264
00281 static int dnxTcpWrite(iDnxChannel * icp, char * buf, int size,
00282 int timeout, char * dst)
00283 {
00284 iDnxTcpChannel * itcp = (iDnxTcpChannel *)
00285 ((char *)icp - offsetof(iDnxTcpChannel, ichan));
00286 unsigned short mlen;
00287
00288 assert(icp && itcp->socket && buf && size);
00289
00290
00291 if (timeout > 0)
00292 {
00293 struct timeval tv;
00294 fd_set fd_wrs;
00295 int nsd;
00296
00297 FD_ZERO(&fd_wrs);
00298 FD_SET(itcp->socket, &fd_wrs);
00299
00300 tv.tv_usec = 0L;
00301 tv.tv_sec = timeout;
00302
00303 if ((nsd = select(itcp->socket + 1, 0, &fd_wrs, 0, &tv)) == 0)
00304 return DNX_ERR_TIMEOUT;
00305
00306 if (nsd < 0)
00307 {
00308 if (errno != EINTR)
00309 {
00310 dnxLog("dnxTcpWrite: select failed: %s.", strerror(errno));
00311 return DNX_ERR_SEND;
00312 }
00313 return DNX_ERR_TIMEOUT;
00314 }
00315 }
00316
00317
00318 mlen = (unsigned short)size;
00319 mlen = htons(mlen);
00320
00321
00322 if (write(itcp->socket, &mlen, sizeof mlen) != sizeof mlen)
00323 return DNX_ERR_SEND;
00324
00325
00326 if (write(itcp->socket, buf, size) != size)
00327 return DNX_ERR_SEND;
00328
00329 return DNX_OK;
00330 }
00331
00332
00333
00338 static void dnxTcpDelete(iDnxChannel * icp)
00339 {
00340 iDnxTcpChannel * itcp = (iDnxTcpChannel *)
00341 ((char *)icp - offsetof(iDnxTcpChannel, ichan));
00342
00343 assert(icp && itcp->socket == 0);
00344
00345 xfree(itcp->host);
00346 xfree(itcp);
00347 }
00348
00349
00350
00359 static int dnxTcpNew(char * url, iDnxChannel ** icpp)
00360 {
00361 char * cp, * ep, * lastchar;
00362 iDnxTcpChannel * itcp;
00363 long port;
00364
00365 assert(icpp && url && *url);
00366
00367
00368 if ((cp = strstr(url, "://")) == 0)
00369 return DNX_ERR_BADURL;
00370 cp += 3;
00371
00372
00373 if ((ep = strchr(cp, ':')) == 0 || ep == cp || ep - cp > HOST_NAME_MAX)
00374 return DNX_ERR_BADURL;
00375
00376
00377 if ((port = strtol(ep + 1, &lastchar, 0)) < 1 || port > 65535
00378 || (*lastchar && *lastchar != '/'))
00379 return DNX_ERR_BADURL;
00380
00381
00382 if ((itcp = (iDnxTcpChannel *)xmalloc(sizeof *itcp)) == 0)
00383 return DNX_ERR_MEMORY;
00384 memset(itcp, 0, sizeof *itcp);
00385
00386
00387 if ((itcp->host = (char *)xmalloc(ep - cp + 1)) == 0)
00388 {
00389 xfree(itcp);
00390 return DNX_ERR_MEMORY;
00391 }
00392 memcpy(itcp->host, cp, ep - cp);
00393 itcp->host[ep - cp] = 0;
00394 itcp->port = (int)port;
00395
00396
00397 itcp->ichan.txOpen = dnxTcpOpen;
00398 itcp->ichan.txClose = dnxTcpClose;
00399 itcp->ichan.txRead = dnxTcpRead;
00400 itcp->ichan.txWrite = dnxTcpWrite;
00401 itcp->ichan.txDelete = dnxTcpDelete;
00402
00403 *icpp = &itcp->ichan;
00404
00405 return DNX_OK;
00406 }
00407
00408
00409
00410
00411
00419 int dnxTcpInit(int (**ptxAlloc)(char * url, iDnxChannel ** icpp))
00420 {
00421 DNX_PT_MUTEX_INIT(&tcpMutex);
00422
00423 *ptxAlloc = dnxTcpNew;
00424
00425 return DNX_OK;
00426 }
00427
00428
00429
00432 void dnxTcpDeInit(void)
00433 {
00434 DNX_PT_MUTEX_DESTROY(&tcpMutex);
00435 }
00436
00437
00438