]> git.vomp.tv Git - vompserver.git/blob - dsock.c
*** empty log message ***
[vompserver.git] / dsock.c
1 /*
2     Copyright 2004-2005 Chris Tallon
3
4     This file is part of VOMP.
5
6     VOMP is free software; you can redistribute it and/or modify
7     it under the terms of the GNU General Public License as published by
8     the Free Software Foundation; either version 2 of the License, or
9     (at your option) any later version.
10
11     VOMP is distributed in the hope that it will be useful,
12     but WITHOUT ANY WARRANTY; without even the implied warranty of
13     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14     GNU General Public License for more details.
15
16     You should have received a copy of the GNU General Public License
17     along with VOMP; if not, write to the Free Software
18     Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
19 */
20
21 #include "dsock.h"
22
23 DatagramSocket::DatagramSocket()
24 {
25   addrlen = sizeof(struct sockaddr);
26   log = Log::getInstance();
27   initted = 0;
28 }
29
30 DatagramSocket::~DatagramSocket()
31 {
32   if (initted) close(socketnum);
33   initted = 0;
34 }
35
36 bool DatagramSocket::init(short port)
37 {
38   myPort = port;
39   if ((socketnum = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) == -1)
40   {
41     log->log("UDP", Log::CRIT, "Socket error");
42     return false;
43   }
44
45   myAddr.sin_family = AF_INET;         // host byte order
46   myAddr.sin_port = htons(myPort);     // short, network byte order
47   myAddr.sin_addr.s_addr = INADDR_ANY; // auto-fill with my IP
48   memset(&(myAddr.sin_zero), 0, 8);    // zero the rest of the struct
49   if (bind(socketnum, (struct sockaddr *)&myAddr, addrlen) == -1)
50   {
51     log->log("UDP", Log::CRIT, "Bind error");
52     close(socketnum);
53     return false;
54   }
55
56   FD_ZERO(&readfds);
57   FD_SET(socketnum, &readfds);
58   tv.tv_sec = 0;
59   tv.tv_usec = 0;
60
61   initted = 1;
62   return true;
63 }
64
65 unsigned char DatagramSocket::waitforMessage(unsigned char how)
66 {
67   if (!initted) return 0;
68
69   /* how = 0 - block
70      how = 1 - start new wait
71      how = 2 - continue wait
72   */
73
74   struct timeval* passToSelect = NULL;
75
76
77   if (how == 0)
78   {
79     passToSelect = NULL;
80   }
81   else if (how == 1)
82   {
83     tv.tv_sec = 1;
84     tv.tv_usec = 100000;
85     passToSelect = &tv;
86   }
87   else if (how == 2)
88   {
89     if ((tv.tv_sec == 0) && (tv.tv_usec == 0))  // protection in case timer = 0
90     {
91       tv.tv_sec = 1;
92       tv.tv_usec = 100000;
93     }
94     passToSelect = &tv;
95   }
96   FD_ZERO(&readfds);
97   FD_SET(socketnum, &readfds);
98
99   if (select(socketnum + 1, &readfds, NULL, NULL, passToSelect) <= 0) return 1;
100
101   if ((mlength = recvfrom(socketnum, buf, MAXBUFLEN, 0, (struct sockaddr *)&theirAddr, &addrlen)) == -1)
102   {
103     log->log("UDP", Log::DEBUG, "recvfrom error");
104     return 0;
105   }
106   else
107   {
108     memset(&buf[mlength], 0, MAXBUFLEN - mlength);
109     strcpy(fromIPA, inet_ntoa(theirAddr.sin_addr));
110     fromPort = ntohs(theirAddr.sin_port);
111     log->log("UDP", Log::DEBUG, "%s:%i received length %i", fromIPA, fromPort, mlength);
112     return 2;
113   }
114
115   /* Return 0, failure
116      Return 1, nothing happened, timer expired
117      Return 2, packet arrived (timer not expired)
118   */
119 }
120
121 int DatagramSocket::getDataLength(void) const
122 {
123   return mlength;
124 }
125
126 char *DatagramSocket::getData(void)             {  return buf;  }
127 char *DatagramSocket::getFromIPA(void)          {  return fromIPA;  }
128 short DatagramSocket::getFromPort(void) const   {  return fromPort; }
129
130 void DatagramSocket::send(char *ipa, short port, char *message, int length)
131 {
132   int sentLength = 0;
133
134   theirAddr.sin_family = AF_INET;      // host byte order
135   theirAddr.sin_port = htons(port);    // short, network byte order
136   struct in_addr tad;                  // temp struct tad needed to pass to theirAddr.sin_addr
137   tad.s_addr = inet_addr(ipa);
138   theirAddr.sin_addr = tad;            // address
139   memset(&(theirAddr.sin_zero), 0, 8); // zero the rest of the struct
140
141   sentLength = sendto(socketnum, message, length, 0, (struct sockaddr *)&theirAddr, addrlen);
142   if (sentLength == length)
143   {
144     log->log("UDP", Log::DEBUG, "%s:%i sent length %i", ipa, port, length);
145     return;
146   }
147
148   log->log("UDP", Log::DEBUG, "%s:%i send failed %i", ipa, port, length);
149
150   sentLength = sendto(socketnum, message, length, 0, (struct sockaddr *)&theirAddr, addrlen);
151   if (sentLength == length)
152   {
153     log->log("UDP", Log::DEBUG, "%s:%i sent length %i 2nd try", ipa, port, length);
154     return;
155   }
156
157   log->log("UDP", Log::DEBUG, "%s:%i send failed %i 2nd try", ipa, port, length);
158 }
159