ns-3 Direct Code Execution
API
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
local-stream-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"
22 #include "local-stream-socket-fd.h"
24 #include "utils.h"
25 #include "process.h"
26 #include "ns3/log.h"
27 #include <errno.h>
28 #include <fcntl.h>
29 #include <sys/un.h>
30 #include "unix-fd.h"
31 #include <exception>
32 #include <poll.h>
33 #include <unistd.h>
34 #include "wait-queue.h"
35 #include "ns3/simulator.h"
36 #include "file-usage.h"
37 
38 NS_LOG_COMPONENT_DEFINE ("LocalStreamSocketFd");
39 
40 namespace ns3 {
41 TypeId
43 {
44  static TypeId tid = TypeId ("ns3::LocalStreamSocketFd").SetParent<LocalSocketFd> ();
45 
46  return tid;
47 }
48 TypeId
50 {
52 }
53 LocalStreamSocketFd::LocalStreamSocketFd (Ptr<LocalSocketFdFactory> f)
54  : m_state (CREATED),
55  m_backLog (0)
56 {
57  NS_LOG_FUNCTION (this);
58  m_factory = f;
59 }
60 
62  : m_state (CONNECTED),
63  m_backLog (0),
64  m_peer (peer)
65 {
66  NS_LOG_FUNCTION (this);
67  m_bindPath = bindPath;
68 }
69 
71 {
72  NS_LOG_FUNCTION (this);
73 
74  ClearAll (false);
75 }
76 
77 void
79 {
80  NS_LOG_FUNCTION (this);
81  ClearAll (false);
83 }
84 
85 int
87 {
88  Thread *current = Current ();
89  NS_LOG_FUNCTION (this);
90  NS_ASSERT (current != 0);
91 
92  NS_LOG_DEBUG ("m_state: " << m_state);
93 
94  switch (m_state)
95  {
96  case CREATED:
97  {
98  ClearAll (false);
99  return 0;
100  }
101 
102  case BINDED:
103  case LISTENING:
104  case ACCEPTING:
105  {
106  NS_ASSERT (0 != m_factory);
107  m_factory->UnRegisterBinder (m_bindPath);
108  m_bindPath = "";
110 
111  return 0;
112  }
113 
114  case CONNECTING:
115  {
116  ClearAll (true);
117  return 0;
118  }
119 
120  case CONNECTED:
121  {
122  NS_ASSERT (m_peer != 0);
123  m_peer->PeerClosed ();
124 
125  ClearAll (true);
126 
127  return 0;
128  }
129 
130  case REMOTECLOSED:
131  {
132  ClearAll (false);
133  return 0;
134  }
135 
136  case CLOSED:
137  {
138  return 0;
139  }
140 
141  default:
142  break;
143  }
144 
145  current->err = EBADF;
146  return -1;
147 }
148 
149 
150 ssize_t
151 LocalStreamSocketFd::Write (const void *buf, size_t count)
152 {
153  Thread *current = Current ();
154  NS_LOG_FUNCTION (this << buf << count);
155  NS_ASSERT (current != 0);
156 
157  NS_LOG_DEBUG ("Write enter state " << m_state);
158 
159  if (m_state != CONNECTED)
160  {
161  if (m_state == REMOTECLOSED)
162  {
163  return 0;
164  }
165  current->err = ENOTCONN;
166  return -1;
167  }
168  if (m_shutWrite)
169  {
170  current->err = EPIPE;
171  return -1;
172  }
173 
174  NS_ASSERT (m_peer != 0);
175 
176  size_t tot = 0;
177 
178  WaitQueueEntryTimeout *wq = 0;
179  do
180  {
181  ssize_t lg = m_peer->DoRecvPacket ((uint8_t*) buf + tot, count - tot);
182  NS_LOG_FUNCTION (this << " lg:" << lg);
183  if (0 == lg)
184  {
185  if (m_statusFlags & O_NONBLOCK)
186  {
187  // Socket do not want to wait
188  Current ()->err = EAGAIN;
189  RETURNFREE (-1);
190  }
191  if (!wq)
192  {
193  wq = new WaitQueueEntryTimeout (POLLOUT | POLLHUP, GetSendTimeout ());
194  }
195  AddWaitQueue (wq, true);
196  PollTable::Result res = wq->Wait ();
197  RemoveWaitQueue (wq, true);
198 
199  switch (res)
200  {
201  case PollTable::OK:
202  break;
204  UtilsDoSignal ();
205  if (tot != 0)
206  {
207  // this is a short write
208  RETURNFREE (tot);
209  }
210  else
211  {
212  current->err = EINTR;
213  RETURNFREE (-1);
214  }
215  break;
216  case PollTable::TIMEOUT:
217  if (tot != 0)
218  {
219  // this is a short write
220  RETURNFREE (tot);
221  }
222  else
223  {
224  current->err = EAGAIN;
225  RETURNFREE (-1);
226  }
227  break;
228  }
229  }
230  else if (lg > 0)
231  {
232  tot += lg;
233  }
234  else
235  {
236  if (-2 == lg)
237  {
238  if (0 == tot)
239  {
240  current->err = EPIPE;
241  RETURNFREE (-1);
242  }
243  break;
244  }
245  current->err = ENOMEM;
246  RETURNFREE (-1);
247  }
248  }
249  while ((tot < count) && (m_state == CONNECTED));
250 
251  if ((0 == tot) && (m_state != CONNECTED))
252  {
253  current->err = EPIPE;
254  RETURNFREE (-1);
255  }
256 
257  RETURNFREE (tot);
258 }
259 ssize_t
260 LocalStreamSocketFd::Read (void *buf, size_t count)
261 {
262  Thread *current = Current ();
263  NS_LOG_FUNCTION (this << buf << count);
264  NS_ASSERT (current != 0);
265 
266  NS_LOG_DEBUG ("Read enter state: " << m_state);
267 
268  if ((m_state != CONNECTED) && (m_state != REMOTECLOSED))
269  {
270  current->err = EINVAL;
271  return -1;
272  }
273 
274  size_t filled = 0;
275  WaitQueueEntryTimeout *wq = 0;
276 
277  while ((filled < count) && ((m_state == CONNECTED) || ((REMOTECLOSED == m_state) && (m_readBufferSize > 0))))
278  {
279  size_t lg = ReadData ((uint8_t*) buf + filled, count - filled, false);
280  if (0 == lg)
281  {
282  if (m_statusFlags & O_NONBLOCK)
283  {
284  if (0 == filled)
285  {
286  // Socket do not want to wait
287  Current ()->err = EAGAIN;
288  RETURNFREE (-1);
289  }
290  return filled;
291  }
292  if ((0 != m_peer) && (m_peer->IsShutWrite ()))
293  {
294  RETURNFREE (0);
295  }
296  // Nothing should wait
297 
298  if (!wq)
299  {
300  wq = new WaitQueueEntryTimeout (POLLIN | POLLHUP, GetRecvTimeout ());
301  }
302  AddWaitQueue (wq, true);
303  WaitPoint::Result res = wq->Wait ();
304  RemoveWaitQueue (wq, true);
305 
306  switch (res)
307  {
308  case WaitPoint::OK:
309  break;
311  UtilsDoSignal ();
312  if (filled != 0)
313  {
314  // this is a short read
315  RETURNFREE (filled);
316  }
317  else
318  {
319  current->err = EINTR;
320  RETURNFREE (-1);
321  }
322  break;
323  case WaitPoint::TIMEOUT:
324  if (filled != 0)
325  {
326  // this is a short read
327  RETURNFREE (filled);
328  }
329  else
330  {
331  current->err = EAGAIN;
332  RETURNFREE (-1);
333  }
334  break;
335  }
336  }
337  else if (lg > 0)
338  {
339  filled += lg;
340  if (0 != m_peer)
341  {
342  short po = POLLOUT;
343  m_peer->WakeWaiters (&po);
344  }
345  }
346  else
347  {
348  current->err = ENOMEM;
349  RETURNFREE (-1);
350  }
351  }
352 
353  RETURNFREE (filled);
354 }
355 ssize_t
356 LocalStreamSocketFd::Recvmsg (struct msghdr *msg, int flags)
357 {
358  Thread *current = Current ();
359  NS_LOG_FUNCTION (this << current << msg << flags);
360  NS_ASSERT (current != 0);
361 
362  ssize_t retval = 0;
363  for (uint32_t i = 0; i < msg->msg_iovlen; ++i)
364  {
365  uint8_t *buf = (uint8_t *) msg->msg_iov[i].iov_base;
366  ssize_t len = msg->msg_iov[i].iov_len;
367 
368  size_t ret = Read (buf, len);
369 
370  if ((msg->msg_namelen > 0) && (0 != msg->msg_name))
371  {
372  memset (msg->msg_name, 0, msg->msg_namelen);
373  }
374 
375  msg->msg_namelen = 0;
376 
377  if (ret == 0)
378  {
379  break;
380  }
381  if (ret > 0)
382  {
383  retval += ret;
384  }
385  else
386  {
387  return -1;
388  }
389  }
390 
391  return retval;
392 }
393 ssize_t
394 LocalStreamSocketFd::Sendmsg (const struct msghdr *msg, int flags)
395 {
396  Thread *current = Current ();
397  NS_LOG_FUNCTION (this << current << msg << flags);
398  NS_ASSERT (current != 0);
399 
400  if (msg->msg_name != 0 || msg->msg_namelen != 0)
401  {
402  current->err = EISCONN;
403  return -1;
404  }
405 
406  ssize_t retval = 0;
407  for (uint32_t i = 0; i < msg->msg_iovlen; ++i)
408  {
409  uint8_t *buf = (uint8_t *) msg->msg_iov[i].iov_base;
410  ssize_t len = msg->msg_iov[i].iov_len;
411 
412  size_t ret = Write (buf, len);
413 
414  if (ret == 0)
415  {
416  break;
417  }
418  if (ret > 0)
419  {
420  retval += ret;
421  }
422  else
423  {
424  return -1;
425  }
426  }
427 
428  return retval;
429 }
430 bool
432 {
433  return false;
434 }
435 int
436 LocalStreamSocketFd::Setsockopt (int level, int optname, const void *optval, socklen_t optlen)
437 {
438  Thread *current = Current ();
439  NS_LOG_FUNCTION (this << current << level << optname << optval << optlen);
440  NS_ASSERT (current != 0);
441 
442  if (level != SOL_SOCKET)
443  {
444  current->err = EINVAL;
445  return -1;
446  }
447 
448  switch (optname)
449  {
450 
451  case SO_LINGER:
452  {
453  if ((0 == optval) || (0 == optlen) || (optlen < sizeof(struct linger)))
454  {
455  current->err = EINVAL;
456  return -1;
457  }
458  if (((struct linger *) optval)->l_onoff != 0)
459  {
460  m_linger = (((struct linger *) optval)->l_linger);
461  }
462  else
463  {
464  m_linger = 0;
465  }
466  }
467  break;
468 
469  case SO_PASSCRED:
470  {
471  NS_LOG_DEBUG ("LocalStreamSocketFd SO_PASSCRED NOT IMPLEMENTED");
472  current->err = EINVAL;
473  return -1;
474  }
475 
476  case SO_RCVBUF:
477  case SO_SNDBUF:
478  {
479  NS_LOG_DEBUG ("LocalStreamSocketFd SO_RCVBUF and SO_SNDBUF ignored.");
480  return 0;
481  }
482  case SO_RCVLOWAT:
483  {
484  NS_LOG_DEBUG ("LocalStreamSocketFd SO_RCVLOWAT ignored.");
485  return 0;
486  }
487  case SO_SNDLOWAT:
488  {
489  NS_LOG_DEBUG ("LocalStreamSocketFd SO_SNDLOWAT ignored.");
490  return 0;
491  }
492 
493  case SO_RCVTIMEO:
494  {
495  if ((0 == optval) || (0 == optlen) || (optlen < sizeof(struct timeval)))
496  {
497  current->err = EINVAL;
498  return -1;
499  }
500 
501  m_recvTimeout = UtilsTimevalToTime ((struct timeval *) optval);
502 
503  return 0;
504  }
505 
506  case SO_SNDTIMEO:
507  {
508  if ((0 == optval) || (0 == optlen) || (optlen < sizeof(struct timeval)))
509  {
510  current->err = EINVAL;
511  return -1;
512  }
513 
514  m_sendTimeout = UtilsTimevalToTime ((struct timeval *) optval);
515 
516  return 0;
517  }
518 
519  default:
520  break;
521  }
522  current->err = EINVAL;
523  return -1;
524 }
525 int
526 LocalStreamSocketFd::Getsockopt (int level, int optname, void *optval, socklen_t *optlen)
527 {
528  Thread *current = Current ();
529  NS_LOG_FUNCTION (this << current << level << optname << optval << optlen);
530  NS_ASSERT (current != 0);
531 
532  if (level != SOL_SOCKET)
533  {
534  current->err = EINVAL;
535  return -1;
536  }
537 
538  switch (optname)
539  {
540 
541  case SO_LINGER:
542  {
543  if ((0 == optval) || (0 == optlen) || ((*optlen) < sizeof(struct linger)))
544  {
545  current->err = EINVAL;
546  return -1;
547  }
548  ((struct linger *) optval)->l_linger = m_linger;
549 
550  return 0;
551  }
552  break;
553 
554  case SO_PASSCRED:
555  {
556  NS_LOG_DEBUG ("LocalStreamSocketFd SO_PASSCRED NOT IMPLEMENTED");
557  current->err = EINVAL;
558  return -1;
559  }
560 
561  case SO_RCVBUF:
562  case SO_SNDBUF:
563  {
564  if ((0 == optval) || (0 == optlen) || ((*optlen) < sizeof(int)))
565  {
566  current->err = EINVAL;
567  return -1;
568  }
569 
570  int *ival = (int*)optval;
571 
572  *ival = LOCAL_SOCKET_MAX_BUFFER;
573 
574  (*optlen) = sizeof(int);
575 
576  return 0;
577  }
578  case SO_SNDLOWAT:
579  case SO_RCVLOWAT:
580  {
581  if ((0 == optval) || (0 == optlen) || ((*optlen) < sizeof(int)))
582  {
583  current->err = EINVAL;
584  return -1;
585  }
586 
587  int *ival = (int*)optval;
588 
589  *ival = 1;
590 
591  (*optlen) = sizeof(int);
592 
593  return 0;
594  }
595 
596  case SO_ACCEPTCONN:
597  {
598  if ((0 == optval) || (0 == optlen) || ((*optlen) < sizeof(int)))
599  {
600  current->err = EINVAL;
601  return -1;
602  }
603 
604  int *ival = (int*)optval;
605 
606  *ival = ((m_state == LISTENING)||(m_state == ACCEPTING));
607 
608  (*optlen) = sizeof(int);
609 
610  return 0;
611  }
612 
613  case SO_RCVTIMEO:
614  {
615  if ((0 == optval) || (0 == optlen) || ((*optlen) < sizeof(struct timeval)))
616  {
617  current->err = EINVAL;
618  return -1;
619  }
620 
621  struct timeval *tv = (struct timeval*)optval;
622 
624 
625  return 0;
626  }
627 
628  case SO_SNDTIMEO:
629  {
630  if ((0 == optval) || (0 == optlen) || ((*optlen) < sizeof(struct timeval)))
631  {
632  current->err = EINVAL;
633  return -1;
634  }
635 
636  struct timeval *tv = (struct timeval*)optval;
637 
639 
640  return 0;
641  }
642 
643  case SO_TYPE:
644  {
645  if ((0 == optval) || (0 == optlen) || ((*optlen) < sizeof(int)))
646  {
647  current->err = EINVAL;
648  return -1;
649  }
650 
651  int *ival = (int*)optval;
652 
653  *ival = SOCK_STREAM;
654 
655  (*optlen) = sizeof(int);
656 
657  return 0;
658  }
659 
660  default:
661  {
662  current->err = EINVAL;
663  return -1;
664  }
665  }
666 
667  return -1;
668 }
669 int
670 LocalStreamSocketFd::Getsockname (struct sockaddr *name, socklen_t *namelen)
671 {
672  NS_LOG_FUNCTION (this);
673 
674  if ((0 == name) || (0 == namelen))
675  {
676  Current ()->err = EINVAL;
677  return -1;
678  }
679  struct sockaddr_un address;
680 
681  memset (&address, 0, sizeof(sockaddr_un));
682  address.sun_family = AF_UNIX;
683  if ((m_bindPath.length () > 0)&&(m_state != CLOSED))
684  {
685  std::string root = UtilsGetRealFilePath ("/");
686  std::string virtualPath = m_bindPath.substr (root.length () - 1);
687 
688  memcpy (&address.sun_path, virtualPath.c_str (), std::min (108, (int)virtualPath.length ()));
689  }
690 
691  socklen_t len = std::min ((int) *namelen, (int) sizeof(struct sockaddr_un));
692 
693  memcpy (name, &address, len);
694 
695  *namelen = len;
696 
697  return 0;
698 }
699 int
700 LocalStreamSocketFd::Getpeername (struct sockaddr *name, socklen_t *namelen)
701 {
702  NS_LOG_FUNCTION (this);
703 
704  if ((0 == name) || (0 == namelen))
705  {
706  Current ()->err = EINVAL;
707  return -1;
708  }
709  if ((m_state != CONNECTED) && (m_state != REMOTECLOSED))
710  {
711  Current ()->err = ENOTCONN;
712  return -1;
713  }
714  struct sockaddr_un address;
715 
716  memset (&address, 0, sizeof(sockaddr_un));
717  address.sun_family = AF_UNIX;
718  if (m_connectPath.length () > 0)
719  {
720  std::string root = UtilsGetRealFilePath ("/");
721  std::string virtualPath = m_connectPath.substr (root.length () - 1);
722 
723  memcpy (&address.sun_path, virtualPath.c_str (), std::min (108, (int)virtualPath.length ()));
724  }
725 
726  socklen_t len = std::min ((int) *namelen, (int) sizeof(struct sockaddr_un));
727 
728  memcpy (name, &address, len);
729 
730  *namelen = len;
731 
732  return 0;
733 }
734 int
735 LocalStreamSocketFd::Bind (const struct sockaddr *my_addr, socklen_t addrlen)
736 {
737  NS_LOG_FUNCTION (this);
738 
739  if (my_addr->sa_family != AF_UNIX)
740  {
741  Current ()->err = EINVAL;
742  return -1;
743  }
744 
745  if (m_state != CREATED)
746  {
747  return -1;
748  }
749 
750  std::string realPath = UtilsGetRealFilePath (std::string (((struct sockaddr_un*) my_addr)->sun_path));
751 
752  struct sockaddr_un realAddr;
753 
754  memset (&realAddr, 0, sizeof(realAddr));
755 
756  realAddr.sun_family = my_addr->sa_family;
757 
758  memcpy (&(realAddr.sun_path), realPath.c_str (), std::min (108, (int) realPath.length ()));
759 
760  int realFd = ::socket (AF_UNIX, SOCK_STREAM, 0);
761 
763 
764  int ret = ::bind (realFd, (struct sockaddr *) &realAddr, sizeof(realAddr));
765 
766  if (0 == ret)
767  {
768  m_state = BINDED;
769  m_bindPath = realPath;
770  m_factory->RegisterBinder (m_bindPath, this);
771  }
772  else
773  {
774  Current ()->err = errno;
775  }
776  close (realFd);
777 
778  return ret;
779 }
780 int
781 LocalStreamSocketFd::Connect (const struct sockaddr *my_addr, socklen_t addrlen)
782 {
783  Thread *current = Current ();
784  NS_LOG_FUNCTION (this << current << my_addr << addrlen);
785  NS_ASSERT (current != 0);
786 
787  // first seek bind one
788  if (0 == m_factory)
789  {
790  Current ()->err = EINVAL;
791  return -1;
792  }
793  std::string realPath = UtilsGetRealFilePath (std::string (((struct sockaddr_un*) my_addr)->sun_path));
794  LocalSocketFd* l1 = m_factory->FindBinder (realPath, this->GetTypeId ());
795  LocalStreamSocketFd *listener = (0 == l1) ? 0 : dynamic_cast<LocalStreamSocketFd*> (l1);
796 
797  if (0 != listener)
798  {
799  // There is a good listener ...
800  if (listener->IsAccepting () || listener->IsListening ())
801  {
802  if ((!listener->IsAccepting ()) && (m_statusFlags & O_NONBLOCK))
803  {
804  // Socket do not want to wait
805  Current ()->err = EAGAIN;
806  return -1;
807  }
809 
810  WaitQueueEntryTimeout *wq = new WaitQueueEntryTimeout (POLLIN | POLLHUP, GetRecvTimeout ());
811  AddWaitQueue (wq, true);
812  listener->ConnectionCreated (this, wq);
814  if (m_state == CONNECTING)
815  {
816  res = wq->Wait ();
817  }
818  RemoveWaitQueue (wq, true);
819  delete (wq);
820  wq = 0;
821 
822  if (WaitPoint::INTERRUPTED == res)
823  {
824  UtilsDoSignal ();
825  }
826  if ((m_state == CONNECTED) || (m_state == REMOTECLOSED))
827  {
828  m_connectPath = realPath;
829 
830  return 0;
831  }
832  else
833  {
834  listener->RemoveFromQueue (this);
835  current->err = EAGAIN;
836  }
837  }
838  }
839  else
840  {
841  current->err = ENOENT;
842  }
843 
844  return -1;
845 }
846 int
848 {
849  if (m_state != BINDED)
850  {
851  Current ()->err = EINVAL;
852  return -1;
853  }
854  else
855  {
856  m_backLog = backlog;
857  m_state = LISTENING;
858  m_factory->RegisterBinder (m_bindPath, this);
859  return 0;
860  }
861 }
862 int
864 {
865  NS_LOG_FUNCTION (this << how);
866  if ((m_state != CONNECTED) && (m_state != REMOTECLOSED))
867  {
868  Current ()->err = ENOTCONN;
869  return -1;
870  }
871  switch (how)
872  {
873  case SHUT_RD:
874  {
875  m_shutRead = true;
876  }
877  break;
878 
879  case SHUT_WR:
880  {
881  m_shutWrite = true;
882  }
883  break;
884 
885  case SHUT_RDWR:
886  {
887  m_shutWrite = true;
888  m_shutRead = true;
889  }
890  break;
891  }
892  return 0;
893 }
894 int
895 LocalStreamSocketFd::Accept (struct sockaddr *my_addr, socklen_t *addrlen)
896 {
897  Thread *current = Current ();
898  NS_LOG_FUNCTION (this << current << my_addr << addrlen);
899  NS_ASSERT (current != 0);
900 
901  if (m_state != LISTENING)
902  {
903  Current ()->err = EINVAL;
904  return -1;
905  }
906 
907  WaitQueueEntryTimeout *wq = 0;
908 
909  NS_LOG_DEBUG ("Accept: incoming queue len:" << m_cnxQueue.size ());
910 
911  while (m_cnxQueue.empty ())
912  {
913  if (m_statusFlags & O_NONBLOCK)
914  {
915  // Socket do not want to wait
916  Current ()->err = EAGAIN;
917  RETURNFREE (-1);
918  }
919  m_state = ACCEPTING;
920  if (!wq)
921  {
922  wq = new WaitQueueEntryTimeout (POLLIN | POLLHUP, GetRecvTimeout ());
923  }
924  AddWaitQueue (wq, true);
925  WaitPoint::Result res = wq->Wait ();
926  RemoveWaitQueue (wq, true);
927 
928  switch (res)
929  {
930  case WaitPoint::OK:
931  break;
933  {
934  UtilsDoSignal ();
935  current->err = EINTR;
936  RETURNFREE (-1);
937  }
938  case WaitPoint::TIMEOUT:
939  {
940  current->err = EAGAIN;
941  RETURNFREE (-1);
942  }
943  }
944  }
945 
946  m_state = LISTENING;
947 
948  while (!m_cnxQueue.empty ())
949  {
950  LocalStreamSocketFd* first = m_cnxQueue.front ();
951  m_cnxQueue.pop_front ();
952  // create an fd for the socket.
953  int fd = UtilsAllocateFd ();
954  if (fd == -1)
955  {
956  first->Close ();
957  current->err = EMFILE;
958  RETURNFREE (-1);
959  }
960 
961  if (first->InternalConnect ())
962  {
963  LocalStreamSocketFd *socket = new LocalStreamSocketFd (first, m_bindPath);
964  socket->IncFdCount ();
965  current->process->openFiles[fd] = new FileUsage (fd, socket);
966 
967  first->SetPeer (socket);
968 
969  if ((0 != my_addr) && (0 != addrlen) && ((*addrlen) >= sizeof (sa_family_t)))
970  {
971  my_addr->sa_family = AF_UNIX;
972  *addrlen = sizeof (sa_family_t);
973  }
974 
975  RETURNFREE (fd);
976  }
977 
978  }
979 
980  RETURNFREE (-1);
981 }
982 
983 bool
985 {
986  switch (m_state)
987  {
988  case CONNECTED:
989  case REMOTECLOSED:
990  {
991  return (m_readBufferSize > 0);
992  }
993 
994  case LISTENING:
995  case ACCEPTING:
996  {
997  return m_cnxQueue.size () > 0;
998  }
999 
1000  default:
1001  return 0;
1002  }
1003 }
1004 bool
1006 {
1007  return ((CONNECTED == m_state) && (0 != m_peer) && (m_peer->m_readBufferSize < LOCAL_SOCKET_MAX_BUFFER))
1008  || (CONNECTED != m_state);
1009 }
1010 bool
1012 {
1013  NS_LOG_FUNCTION (this << " state:" << m_state);
1014  return (REMOTECLOSED == m_state);
1015 }
1016 bool
1018 {
1019  NS_LOG_FUNCTION (this << " state:" << m_state);
1020  if (CONNECTING != m_state)
1021  {
1022  return false;
1023  }
1024 
1025  m_state = CONNECTED;
1026 
1027  short pi = POLLIN | POLLOUT;
1028  WakeWaiters (&pi);
1029 
1030  return true;
1031 }
1032 
1033 bool
1035 {
1036  return ACCEPTING == m_state;
1037 }
1038 
1039 bool
1041 {
1042  return LISTENING == m_state;
1043 }
1044 
1045 void
1047 {
1048  NS_LOG_FUNCTION (sock);
1049  m_cnxQueue.push_back (sock);
1050 
1051  short pi = POLLIN;
1052  WakeWaiters (&pi);
1053 }
1054 
1055 void
1057 {
1058  NS_LOG_FUNCTION (sock);
1059  m_cnxQueue.remove (sock);
1060 }
1061 
1062 void
1064 {
1065  m_peer = sock;
1066 }
1067 
1068 void
1070 {
1071  NS_LOG_FUNCTION (this);
1072  m_peer = 0;
1073  if (m_state == CONNECTED)
1074  {
1076 
1077  short ph = POLLHUP;
1078  WakeWaiters (&ph);
1079  }
1080 }
1081 
1082 void
1084 {
1085  m_state = CLOSED;
1086  m_peer = 0;
1087  m_factory = 0;
1088  m_bindPath = m_connectPath = "";
1089  m_cnxQueue.clear ();
1090 
1091  ClearReadBuffer ();
1092 
1093  if (andWakeUp)
1094  {
1095  short ph = POLLHUP;
1096  WakeWaiters (&ph);
1097  }
1098 }
1099 
1100 bool
1102 {
1103  return m_shutWrite;
1104 }
1105 
1106 bool
1108 {
1109  return CLOSED == m_state;
1110 }
1111 
1112 int
1114 {
1115  int ret = 0;
1116 
1117  if (CanRecv ())
1118  {
1119  ret |= POLLIN;
1120  }
1121  if (CanSend ())
1122  {
1123  ret |= POLLOUT;
1124  }
1125  if (IsClosed () || HangupReceived ())
1126  {
1127  ret |= POLLHUP;
1128  }
1129 
1130  if (ptable)
1131  {
1132  ptable->PollWait (this);
1133  }
1134 
1135  return ret;
1136 }
1137 
1138 } // namespace ns3