/[resiprocate]/branches/b-directory-reorg/sip/resiprocate/UdpTransport.cxx
ViewVC logotype

Contents of /branches/b-directory-reorg/sip/resiprocate/UdpTransport.cxx

Parent Directory Parent Directory | Revision Log Revision Log


Revision 5271 - (show annotations) (download)
Thu Aug 18 23:43:07 2005 UTC (14 years, 3 months ago) by jason
File size: 10807 byte(s)
new directory reorg proposal
1 #if defined(HAVE_CONFIG_H)
2 #include "resiprocate/config.hxx"
3 #endif
4
5 #include <memory>
6
7 #include "resiprocate/Helper.hxx"
8 #include "resiprocate/SendData.hxx"
9 #include "resiprocate/SipMessage.hxx"
10 #include "resiprocate/UdpTransport.hxx"
11 #include "resiprocate/os/Data.hxx"
12 #include "resiprocate/os/DnsUtil.hxx"
13 #include "resiprocate/os/Logger.hxx"
14 #include "resiprocate/os/Socket.hxx"
15 #include "resiprocate/os/WinLeakCheck.hxx"
16 #include "resiprocate/os/compat.hxx"
17 #include "resiprocate/stun/stun.h"
18
19 #define RESIPROCATE_SUBSYSTEM Subsystem::TRANSPORT
20
21 using namespace std;
22 using namespace resip;
23
24 UdpTransport::UdpTransport(Fifo<TransactionMessage>& fifo,
25 int portNum,
26 IpVersion version,
27 StunSetting stun,
28 const Data& pinterface)
29 : InternalTransport(fifo, portNum, version, pinterface)
30 {
31 InfoLog (<< "Creating UDP transport host=" << pinterface
32 << " port=" << portNum
33 << " ipv4=" << bool(version==V4) );
34
35 mTuple.setType(transport());
36 mFd = InternalTransport::socket(transport(), version);
37 bind();
38 }
39
40 UdpTransport::~UdpTransport()
41 {
42 DebugLog (<< "Shutting down " << mTuple);
43 }
44
45 void
46 UdpTransport::process(FdSet& fdset)
47 {
48 // pull buffers to send out of TxFifo
49 // receive datagrams from fd
50 // preparse and stuff into RxFifo
51
52 if (mTxFifo.messageAvailable() && fdset.readyToWrite(mFd))
53 {
54 std::auto_ptr<SendData> sendData = std::auto_ptr<SendData>(mTxFifo.getNext());
55 //DebugLog (<< "Sent: " << sendData->data);
56 //DebugLog (<< "Sending message on udp.");
57
58 assert( &(*sendData) );
59 assert( sendData->destination.getPort() != 0 );
60
61 const sockaddr& addr = sendData->destination.getSockaddr();
62 int count = sendto(mFd,
63 sendData->data.data(), sendData->data.size(),
64 0, // flags
65 &addr, sendData->destination.length());
66
67 if ( count == SOCKET_ERROR )
68 {
69 int e = getErrno();
70 error(e);
71 InfoLog (<< "Failed (" << e << ") sending to " << sendData->destination);
72 fail(sendData->transactionId);
73 }
74 else
75 {
76 if (count != int(sendData->data.size()) )
77 {
78 ErrLog (<< "UDPTransport - send buffer full" );
79 fail(sendData->transactionId);
80 }
81 }
82 }
83
84 // !jf! this may have to change - when we read a message that is too big
85 if ( fdset.readyToRead(mFd) )
86 {
87 //should this buffer be allocated on the stack and then copied out, as it
88 //needs to be deleted every time EWOULDBLOCK is encountered
89 // .dlb. can we determine the size of the buffer before we allocate?
90 // something about MSG_PEEK|MSG_TRUNC in Stevens..
91 // .dlb. RFC3261 18.1.1 MUST accept 65K datagrams. would have to attempt to
92 // adjust the UDP buffer as well...
93 char* buffer = new char[MaxBufferSize + 5];
94
95 // !jf! how do we tell if it discarded bytes
96 // !ah! we use the len-1 trick :-(
97 Tuple tuple(mTuple);
98 socklen_t slen = tuple.length();
99 int len = recvfrom( mFd,
100 buffer,
101 MaxBufferSize,
102 0 /*flags */,
103 &tuple.getMutableSockaddr(),
104 &slen);
105 if ( len == SOCKET_ERROR )
106 {
107 int err = getErrno();
108 if ( err != EWOULDBLOCK )
109 {
110 error( err );
111 }
112 }
113
114 if (len == 0 || len == SOCKET_ERROR)
115 {
116 delete[] buffer;
117 buffer=0;
118 return;
119 }
120
121 if (len+1 >= MaxBufferSize)
122 {
123 InfoLog(<<"Datagram exceeded max length "<<MaxBufferSize);
124 delete [] buffer; buffer=0;
125 return;
126 }
127
128 //handle incoming CRLFCRLF keep-alive packets
129 if (len == 4 &&
130 strncmp(buffer, Symbols::CRLFCRLF, len) == 0)
131 {
132 StackLog(<<"Throwing away incoming firewall keep-alive");
133 return;
134 }
135 // this must be a STUN request (or garbage)
136 if (buffer[0] == 0 || buffer[0] == 1 && ipVersion() == V4)
137 {
138 bool changePort = false;
139 bool changeIp = false;
140
141 StunAddress4 myAddr;
142 const sockaddr_in& bi = (const sockaddr_in&)boundInterface();
143 myAddr.addr = ntohl(bi.sin_addr.s_addr);
144 myAddr.port = ntohs(bi.sin_port);
145
146 StunAddress4 from; // packet source
147 const sockaddr_in& fi = (const sockaddr_in&)tuple.getSockaddr();
148 from.addr = ntohl(fi.sin_addr.s_addr);
149 from.port = ntohs(fi.sin_port);
150
151 StunMessage resp;
152 StunAddress4 dest;
153 StunAtrString hmacPassword;
154 hmacPassword.sizeValue = 0;
155
156 StunAddress4 secondary;
157 secondary.port = 0;
158 secondary.addr = 0;
159
160 bool ok = stunServerProcessMsg( buffer, len, // input buffer
161 from, // packet source
162 secondary, // not used
163 myAddr, // address to fill into response
164 myAddr, // not used
165 &resp, // stun response
166 &dest, // where to send response
167 &hmacPassword, // not used
168 &changePort, // not used
169 &changeIp, // not used
170 false ); // logging
171
172 if (ok)
173 {
174 char* response = new char[STUN_MAX_MESSAGE_SIZE];
175 int rlen = stunEncodeMessage( resp,
176 response,
177 STUN_MAX_MESSAGE_SIZE,
178 hmacPassword,
179 false );
180 SendData* stunResponse = new SendData(tuple, response, rlen);
181 mTxFifo.add(stunResponse);
182 }
183 return;
184 }
185
186
187 buffer[len]=0; // null terminate the buffer string just to make debug easier and reduce errors
188
189 //DebugLog ( << "UDP Rcv : " << len << " b" );
190 //DebugLog ( << Data(buffer, len).escaped().c_str());
191
192 SipMessage* message = new SipMessage(this);
193
194 // set the received from information into the received= parameter in the
195 // via
196
197 // It is presumed that UDP Datagrams are arriving atomically and that
198 // each one is a unique SIP message
199
200
201 // Save all the info where this message came from
202 tuple.transport = this;
203 message->setSource(tuple);
204 //DebugLog (<< "Received from: " << tuple);
205
206 // Tell the SipMessage about this datagram buffer.
207 message->addBuffer(buffer);
208
209
210 mMsgHeaderScanner.prepareForMessage(message);
211
212 char *unprocessedCharPtr;
213 if (mMsgHeaderScanner.scanChunk(buffer,
214 len,
215 &unprocessedCharPtr) !=
216 MsgHeaderScanner::scrEnd)
217 {
218 StackLog(<<"Scanner rejecting datagram as unparsable / fragmented from " << tuple);
219 StackLog(<< Data(buffer, len));
220 delete message;
221 message=0;
222 return;
223 }
224
225 // no pp error
226 int used = unprocessedCharPtr - buffer;
227
228 if (used < len)
229 {
230 // body is present .. add it up.
231 // NB. The Sip Message uses an overlay (again)
232 // for the body. It ALSO expects that the body
233 // will be contiguous (of course).
234 // it doesn't need a new buffer in UDP b/c there
235 // will only be one datagram per buffer. (1:1 strict)
236
237 message->setBody(buffer+used,len-used);
238 //DebugLog(<<"added " << len-used << " byte body");
239 }
240
241 if (!basicCheck(*message))
242 {
243 delete message; // cannot use it, so, punt on it...
244 // basicCheck queued any response required
245 message = 0;
246 return;
247 }
248
249 stampReceived(message);
250
251 mStateMachineFifo.add(message);
252 }
253 }
254
255
256 void
257 UdpTransport::buildFdSet( FdSet& fdset )
258 {
259 fdset.setRead(mFd);
260
261 if (mTxFifo.messageAvailable())
262 {
263 fdset.setWrite(mFd);
264 }
265 }
266
267 /* ====================================================================
268 * The Vovida Software License, Version 1.0
269 *
270 * Copyright (c) 2000 Vovida Networks, Inc. All rights reserved.
271 *
272 * Redistribution and use in source and binary forms, with or without
273 * modification, are permitted provided that the following conditions
274 * are met:
275 *
276 * 1. Redistributions of source code must retain the above copyright
277 * notice, this list of conditions and the following disclaimer.
278 *
279 * 2. Redistributions in binary form must reproduce the above copyright
280 * notice, this list of conditions and the following disclaimer in
281 * the documentation and/or other materials provided with the
282 * distribution.
283 *
284 * 3. The names "VOCAL", "Vovida Open Communication Application Library",
285 * and "Vovida Open Communication Application Library (VOCAL)" must
286 * not be used to endorse or promote products derived from this
287 * software without prior written permission. For written
288 * permission, please contact vocal@vovida.org.
289 *
290 * 4. Products derived from this software may not be called "VOCAL", nor
291 * may "VOCAL" appear in their name, without prior written
292 * permission of Vovida Networks, Inc.
293 *
294 * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESSED OR IMPLIED
295 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
296 * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, TITLE AND
297 * NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT SHALL VOVIDA
298 * NETWORKS, INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT DAMAGES
299 * IN EXCESS OF $1,000, NOR FOR ANY INDIRECT, INCIDENTAL, SPECIAL,
300 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
301 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
302 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
303 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
304 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
305 * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
306 * DAMAGE.
307 *
308 * ====================================================================
309 *
310 * This software consists of voluntary contributions made by Vovida
311 * Networks, Inc. and many individuals on behalf of Vovida Networks,
312 * Inc. For more information on Vovida Networks, Inc., please see
313 * <http://www.vovida.org/>.
314 *
315 */

Properties

Name Value
svn:eol-style LF

webmaster AT resiprocate DOT org
ViewVC Help
Powered by ViewVC 1.1.27