2 * Copyright (c) 2004 Teodor Sigaev <teodor@sigaev.ru>
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 * 3. Neither the name of the author nor the names of any co-contributors
14 * may be used to endorse or promote products derived from this software
15 * without specific prior written permission.
17 * THIS SOFTWARE IS PROVIDED BY CONTRIBUTORS ``AS IS'' AND ANY EXPRESS
18 * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
19 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20 * ARE DISCLAIMED. IN NO EVENT SHALL CONTRIBUTORS BE LIABLE FOR ANY
21 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
23 * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
24 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
25 * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
26 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
27 * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
41 #include "connection.h"
46 TC_AcceptUdp(char *host, int port) {
47 struct sockaddr_in serv_addr;
50 if ( (sockfd = socket(AF_INET, SOCK_DGRAM, 0)) < 0)
51 tlog(TL_CRIT|TL_EXIT, "udp socket %s", strerror(errno));
52 if ((flags=fcntl(sockfd,F_GETFL,0)) == -1)
53 tlog(TL_ALARM,"fcntl F_GETFL - %s",strerror(errno));
55 if (fcntl(sockfd,F_SETFL,flags|O_NDELAY) < 0 )
56 tlog(TL_ALARM,"fcntl O_NDELAY - %s",strerror(errno));
58 memset(&serv_addr, 0, sizeof(serv_addr));
59 serv_addr.sin_family = AF_INET;
60 serv_addr.sin_addr.s_addr = (host && *host!='*') ? inet_addr(host) : htonl(INADDR_ANY);
61 if ( serv_addr.sin_addr.s_addr == INADDR_NONE ) {
62 struct hostent *ip_host;
65 * Can't parse address: it's a DNS Name
67 ip_host = gethostbyname(host);
68 if ( ip_host && ip_host->h_addrtype == AF_INET ) {
69 memcpy(&serv_addr.sin_addr.s_addr, ip_host->h_addr_list[0],
70 sizeof(&serv_addr.sin_addr.s_addr));
72 tlog(TL_CRIT,"gethostbyname: %s - %s", host, hstrerror(h_errno));
77 serv_addr.sin_port = htons(port);
79 if (bind(sockfd, (struct sockaddr *) &serv_addr, sizeof(serv_addr)) < 0)
80 tlog(TL_CRIT|TL_EXIT, "cannot bind to %s address: %s",
81 inet_ntoa(serv_addr.sin_addr), strerror(errno));
86 #define MSGMAXSIZE 8192
87 char pc_msg_buf[MSGMAXSIZE];
90 TC_getMsg( int sockfd, Msg *msg ) {
91 struct sockaddr_in cli_addr;
93 socklen_t clilen = sizeof(cli_addr);
94 TCMsg *pmsg = (TCMsg*)pc_msg_buf;
96 n = recvfrom(sockfd, pc_msg_buf, MSGMAXSIZE, 0, (struct sockaddr *)&cli_addr, &clilen);
99 if ( errno == EAGAIN || errno == EWOULDBLOCK)
101 tlog(TL_ALARM, "recvfrom error: %s", strerror(errno));
105 if ( n<TCMSGHDRSZ ) {
106 tlog(TL_ALARM, "Got message %d bytes (should be al least %d)", n, TCMSGHDRSZ );
111 * convert from network byteorder
113 pmsg->len = ntohl(pmsg->len);
114 pmsg->type = ntohl(pmsg->type);
116 if ( pmsg->len > MSGMAXSIZE ) {
117 tlog(TL_ALARM, "Messages (%d bytes) is too big", pmsg->len);
121 if ( pmsg->len != n ) {
122 tlog(TL_ALARM, "Wrong size of messages (got %d bytes, should be %d bytes)", n, pmsg->len);
126 memcpy( &(msg->host_addr), &cli_addr, clilen );
134 TC_sendMsg( Msg *msg ) {
137 if ( msg->msg == NULL || msg->msg->len <=0 )
140 if ( msg->msg->len > MSGMAXSIZE )
143 if ( msg->sockfd <=0 ) {
144 struct sockaddr_in cli_addr;
146 if ( (msg->sockfd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
147 tlog(TL_CRIT,"udp socket %s %d: %s", msg->host, msg->port, strerror(errno));
151 memset(&cli_addr, 0, sizeof(cli_addr));
152 cli_addr.sin_family = AF_INET;
153 cli_addr.sin_addr.s_addr = htonl(INADDR_ANY);
154 cli_addr.sin_port = htons(0);
156 if (bind(msg->sockfd, (struct sockaddr *) &cli_addr, sizeof(cli_addr)) < 0) {
157 tlog(TL_CRIT, "cannot bind to address: %s", strerror(errno));
162 memset(&(msg->host_addr), 0, sizeof(msg->host_addr));
163 msg->host_addr.sin_family = AF_INET;
164 msg->host_addr.sin_addr.s_addr = inet_addr(msg->host);
165 if ( msg->host_addr.sin_addr.s_addr == INADDR_NONE ) {
166 struct hostent *ip_host;
169 * Can't parse address: it's a DNS Name
171 ip_host = gethostbyname(msg->host);
172 if ( ip_host && ip_host->h_addrtype == AF_INET ) {
173 memcpy(&msg->host_addr.sin_addr.s_addr, ip_host->h_addr_list[0],
174 sizeof(&msg->host_addr.sin_addr.s_addr));
176 tlog(TL_CRIT,"gethostbyname: %s - %s", msg->host, hstrerror(h_errno));
182 msg->host_addr.sin_port = htons(msg->port);
186 * convert to network byteorder
188 msglen = msg->msg->len;
189 msg->msg->len = htonl(msg->msg->len);
190 msg->msg->type = htonl(msg->msg->type);
192 if (sendto(msg->sockfd, (void*)msg->msg, msglen, 0, (struct sockaddr *) &(msg->host_addr), sizeof(msg->host_addr)) != msglen) {
193 tlog(TL_CRIT,"Can't send message to %s:%d : %s", msg->host, msg->port, strerror(errno));
203 TC_closefd( Msg *msg ) {
204 if ( msg->sockfd > 0 )