ns-3 Direct Code Execution
API
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
local-socket-fd.cc
Go to the documentation of this file.
1 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
2 /*
3  * Copyright (c) 2011 INRIA
4  *
5  * This program is free software; you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License version 2 as
7  * published by the Free Software Foundation;
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, write to the Free Software
16  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17  *
18  * Author: Frederic Urbani <frederic.urbani@inria.fr>
19  *
20  */
21 #include "local-socket-fd.h"
23 #include "utils.h"
24 #include "process.h"
25 #include "ns3/log.h"
26 #include <errno.h>
27 #include <fcntl.h>
28 #include <sys/mman.h> // for MAP_FAILED
29 #include <sys/un.h>
30 #include "unix-fd.h"
31 #include <exception>
32 #include "poll.h"
33 
34 NS_LOG_COMPONENT_DEFINE ("LocalSocketFd");
35 
36 namespace ns3 {
37 TypeId
39 {
40  static TypeId tid = TypeId ("ns3::LocalSocketFd").SetParent<UnixFd> ();
41 
42  return tid;
43 }
44 TypeId
46 {
47  return LocalSocketFd::GetTypeId ();
48 }
49 LocalSocketFd::LocalSocketFd () : m_readBuffer (0),
50  m_readBufferSize (0),
51  m_sendTimeout (0),
52  m_recvTimeout (0),
53  m_factory (0),
54  m_linger (0),
55  m_bindPath (""),
56  m_connectPath (""),
57  m_shutRead (false),
58  m_shutWrite (false)
59 {
60 }
62 {
63 
64 }
65 bool
67 {
68  return false;
69 }
70 int
71 LocalSocketFd::Setsockopt (int level, int optname, const void *optval, socklen_t optlen)
72 {
73  Thread *current = Current ();
74  NS_LOG_FUNCTION (this << current << level << optname << optval << optlen);
75  NS_ASSERT (current != 0);
76 
77  if (level != SOL_SOCKET)
78  {
79  current->err = EINVAL;
80  return -1;
81  }
82 
83  switch (optname)
84  {
85 
86  case SO_LINGER:
87  {
88  if ((0 == optval) || (0 == optlen) || (optlen < sizeof(struct linger)))
89  {
90  current->err = EINVAL;
91  return -1;
92  }
93  if (((struct linger *) optval)->l_onoff != 0)
94  {
95  m_linger = (((struct linger *) optval)->l_linger);
96  }
97  else
98  {
99  m_linger = 0;
100  }
101  }
102  break;
103 
104  case SO_PASSCRED:
105  {
106  NS_LOG_DEBUG ("LocalSocketFd SO_PASSCRED NOT IMPLEMENTED");
107  current->err = EINVAL;
108  return -1;
109  }
110 
111  case SO_RCVBUF:
112  case SO_SNDBUF:
113  {
114  NS_LOG_DEBUG ("LocalSocketFd SO_RCVBUF and SO_SNDBUF ignored.");
115  return 0;
116  }
117  case SO_RCVLOWAT:
118  {
119  NS_LOG_DEBUG ("LocalSocketFd SO_RCVLOWAT ignored.");
120  return 0;
121  }
122  case SO_SNDLOWAT:
123  {
124  NS_LOG_DEBUG ("LocalSocketFd SO_SNDLOWAT ignored.");
125  return 0;
126  }
127 
128  case SO_RCVTIMEO:
129  {
130  if ((0 == optval) || (0 == optlen) || (optlen < sizeof(struct timeval)))
131  {
132  current->err = EINVAL;
133  return -1;
134  }
135 
136  m_recvTimeout = UtilsTimevalToTime ((struct timeval *) optval);
137 
138  return 0;
139  }
140 
141  case SO_SNDTIMEO:
142  {
143  if ((0 == optval) || (0 == optlen) || (optlen < sizeof(struct timeval)))
144  {
145  current->err = EINVAL;
146  return -1;
147  }
148 
149  m_sendTimeout = UtilsTimevalToTime ((struct timeval *) optval);
150 
151  return 0;
152  }
153 
154  default:
155  break;
156  }
157  current->err = EINVAL;
158  return -1;
159 }
160 int
161 LocalSocketFd::Ioctl (int request, char *argp)
162 {
163  Current ()->err = EINVAL;
164  return -1;
165 }
166 void *
167 LocalSocketFd::Mmap (void *start, size_t length, int prot, int flags, off64_t offset)
168 {
169  GET_CURRENT (start << length << prot << flags << offset);
170  current->err = ENODEV;
171  return MAP_FAILED;
172 }
173 off64_t
174 LocalSocketFd::Lseek (off64_t offset, int whence)
175 {
176  GET_CURRENT (offset << whence);
177  current->err = ESPIPE;
178  return -1;
179 }
180 int
181 LocalSocketFd::Fxstat (int ver, struct ::stat *buf)
182 {
183  GET_CURRENT (ver << buf);
184  buf->st_mode = S_IFSOCK;
185  buf->st_dev = -1;
186  buf->st_blksize = 0;
187  return 0;
188 }
189 int
190 LocalSocketFd::Fxstat64 (int ver, struct ::stat64 *buf)
191 {
192  GET_CURRENT (ver << buf);
193  buf->st_mode = S_IFSOCK;
194  buf->st_dev = -1;
195  buf->st_blksize = 0;
196  return 0;
197 }
198 int
199 LocalSocketFd::Fcntl (int cmd, unsigned long arg)
200 {
201  return UnixFd::Fcntl (cmd, arg);
202 }
203 int
204 LocalSocketFd::Settime (int flags, const struct itimerspec *new_value, struct itimerspec *old_value)
205 {
206  NS_LOG_FUNCTION (this << Current () << flags << new_value << old_value);
207  NS_ASSERT (Current () != 0);
208  Thread *current = Current ();
209  current->err = EINVAL;
210  return -1;
211 }
212 int
213 LocalSocketFd::Gettime (struct itimerspec *cur_value) const
214 {
215  NS_LOG_FUNCTION (this << Current () << cur_value);
216  NS_ASSERT (Current () != 0);
217  Thread *current = Current ();
218  current->err = EINVAL;
219  return -1;
220 }
221 Time
223 {
224  return m_recvTimeout;
225 }
226 Time
228 {
229  return m_sendTimeout;
230 }
231 
232 // Return :
233 // the size readed ,
234 // or 0 if no more space available,
235 // or -1 if fatal error occurs
236 ssize_t
237 LocalSocketFd::DoRecvPacket (uint8_t* buf, size_t len)
238 {
239  NS_LOG_FUNCTION (this << len << " shutRead:" << m_shutRead << "Closed:" << IsClosed ());
240 
241  if ((m_shutRead)|| IsClosed ())
242  {
243  return -2;
244  }
246  {
247  return 0;
248  }
249 
251 
252  int l = std::min (maxi, len);
253 
254  struct Buffer *myBuf = new struct Buffer;
255 
256  myBuf->data = (uint8_t*) malloc (l);
257  if (0 == myBuf->data)
258  {
259  Thread *current = Current ();
260  NS_ASSERT (current != 0);
261  current->err = ENOMEM;
262  return -1;
263  }
264  myBuf->readOffset = 0;
265  myBuf->size = l;
266 
267  memcpy (myBuf->data, buf, l);
268 
269  m_readBuffer.push_back (myBuf);
270 
271  m_readBufferSize += l;
272 
273  NS_LOG_DEBUG ("DoRecvPacket before WakeUpRecv");
274 
275  short pi = POLLIN;
276  WakeWaiters (&pi); // WakeUp reader or poller for read or select for read
277 
278  return l;
279 }
280 
281 size_t
282 LocalSocketFd::ReadData (uint8_t* buf, size_t len, bool peek)
283 {
284  size_t fill = 0;
285  size_t rest = len;
286 
287  if (peek)
288  {
289  for (std::list<struct Buffer*>::iterator i = m_readBuffer.begin (); i != m_readBuffer.end (); ++i)
290  {
291  if ((fill >= len) || (rest <= 0))
292  {
293  break;
294  }
295 
296  struct Buffer* myBuf = *i;
297 
298  size_t avail = std::min (rest, myBuf->size - myBuf->readOffset);
299  NS_LOG_DEBUG ("ReadData avail:" << avail << " offset:" << myBuf->readOffset << " size:" << myBuf->size);
300 
301  if (avail > 0)
302  {
303  memcpy (buf + fill, myBuf->data + myBuf->readOffset, avail);
304  fill += avail;
305  rest -= avail;
306  }
307  }
308  }
309  else
310  {
311  while ((fill < len) && (m_readBuffer.size () > 0) && (rest > 0))
312  {
313  struct Buffer* myBuf = m_readBuffer.front ();
314 
315  size_t avail = std::min (rest, myBuf->size - myBuf->readOffset);
316  NS_LOG_DEBUG ("ReadData avail:" << avail << " offset:" << myBuf->readOffset << " size:" << myBuf->size);
317 
318  if (avail > 0)
319  {
320  memcpy (buf + fill, myBuf->data + myBuf->readOffset, avail);
321  fill += avail;
322  rest -= avail;
323 
324  m_readBufferSize -= avail;
325  myBuf->readOffset += avail;
326 
327  if (myBuf->readOffset >= myBuf->size)
328  {
329  free (myBuf->data);
330  myBuf->data = 0;
331  m_readBuffer.pop_front ();
332  delete myBuf;
333  }
334  }
335  else
336  {
337  break;
338  }
339  }
340  }
341  return fill;
342 }
343 
344 void
346 {
347  NS_LOG_FUNCTION (this);
348  for (std::list<struct Buffer *>::iterator i = m_readBuffer.begin (); i != m_readBuffer.end (); ++i)
349  {
350  struct Buffer *b = *i;
351  if (0 != b->data)
352  {
353  free (b->data);
354  }
355  b->data = 0;
356  b->size = 0;
357  b->readOffset = 0;
358  delete b;
359  }
360  m_readBuffer.clear ();
361  m_readBufferSize = 0;
362 }
363 
364 int
366 {
367  Thread *current = Current ();
368  NS_ASSERT (current != 0);
369  NS_LOG_FUNCTION (this << current << length);
370 
371  current->err = EINVAL;
372  return -1;
373 }
374 
375 } // namespace ns3