• Skip to content
  • Skip to link menu
Trinity API Reference
  • Trinity API Reference
  • kdecore
 

kdecore

  • kdecore
  • network
kdatagramsocket.cpp
1 /* -*- C++ -*-
2  * Copyright (C) 2003,2004 Thiago Macieira <thiago.macieira@kdemail.net>
3  *
4  *
5  * Permission is hereby granted, free of charge, to any person obtaining
6  * a copy of this software and associated documentation files (the
7  * "Software"), to deal in the Software without restriction, including
8  * without limitation the rights to use, copy, modify, merge, publish,
9  * distribute, sublicense, and/or sell copies of the Software, and to
10  * permit persons to whom the Software is furnished to do so, subject to
11  * the following conditions:
12  *
13  * The above copyright notice and this permission notice shall be included
14  * in all copies or substantial portions of the Software.
15  *
16  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19  * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20  * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21  * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22  * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
23  */
24 
25 #include <config.h>
26 
27 #include <sys/types.h>
28 #include <sys/socket.h>
29 
30 #include "ksocketaddress.h"
31 #include "kresolver.h"
32 #include "ksocketdevice.h"
33 #include "kdatagramsocket.h"
34 
35 using namespace KNetwork;
36 
37 /*
38  * TODO:
39  *
40  * don't use signals and slots to track state changes: use stateChanging
41  *
42  */
43 
44 KDatagramSocket::KDatagramSocket(TQObject* parent, const char *name)
45  : KClientSocketBase(parent, name), d(0L)
46 {
47  peerResolver().setFamily(KResolver::KnownFamily);
48  localResolver().setFamily(KResolver::KnownFamily);
49 
50  peerResolver().setSocketType(SOCK_DGRAM);
51  localResolver().setSocketType(SOCK_DGRAM);
52 
53  localResolver().setFlags(KResolver::Passive);
54 
55  // TQObject::connect(localResolver(), TQT_SIGNAL(finished(KResolverResults)),
56  // this, TQT_SLOT(lookupFinishedLocal()));
57  TQObject::connect(&peerResolver(), TQT_SIGNAL(finished(KResolverResults)),
58  this, TQT_SLOT(lookupFinishedPeer()));
59  TQObject::connect(this, TQT_SIGNAL(hostFound()), this, TQT_SLOT(lookupFinishedLocal()));
60 }
61 
62 KDatagramSocket::~KDatagramSocket()
63 {
64  // KClientSocketBase's destructor closes the socket
65 
66  //delete d;
67 }
68 
69 bool KDatagramSocket::bind(const TQString& node, const TQString& service)
70 {
71  if (state() >= Bound)
72  return false;
73 
74  if (localResolver().isRunning())
75  localResolver().cancel(false);
76 
77  // no, we must do a host lookup
78  localResolver().setAddress(node, service);
79 
80  if (!lookup())
81  return false;
82 
83  // see if lookup has finished already
84  // this also catches blocking mode, since lookup has to finish
85  // its processing if we're in blocking mode
86  if (state() > HostLookup)
87  return doBind();
88 
89  return true;
90 }
91 
92 bool KDatagramSocket::connect(const TQString& node, const TQString& service)
93 {
94  if (state() >= Connected)
95  return true; // already connected
96 
97  if (peerResolver().nodeName() != node ||
98  peerResolver().serviceName() != service)
99  peerResolver().setAddress(node, service); // this resets the resolver's state
100 
101  // KClientSocketBase::lookup only works if the state is Idle or HostLookup
102  // therefore, we store the old state, call the lookup routine and then set
103  // it back.
104  SocketState s = state();
105  setState(s == Connecting ? HostLookup : Idle);
106  bool ok = lookup();
107  if (!ok)
108  {
109  setState(s); // go back
110  return false;
111  }
112 
113  // check if lookup is finished
114  // if we're in blocking mode, then the lookup has to be finished
115  if (state() == HostLookup)
116  {
117  // it hasn't finished
118  setState(Connecting);
119  emit stateChanged(Connecting);
120  return true;
121  }
122 
123  // it has to be finished here
124  if (state() != Connected)
125  {
126  setState(Connecting);
127  emit stateChanged(Connecting);
128  lookupFinishedPeer();
129  }
130 
131  return state() == Connected;
132 }
133 
134 KDatagramPacket KDatagramSocket::receive()
135 {
136  TQ_LONG size = bytesAvailable();
137  if (size == 0)
138  {
139  // nothing available yet to read
140  // wait for data if we're not blocking
141  if (blocking())
142  socketDevice()->waitForMore(-1); // wait forever
143  else
144  {
145  // mimic error
146  setError(IO_ReadError, WouldBlock);
147  emit gotError(WouldBlock);
148  return KDatagramPacket();
149  }
150 
151  // try again
152  size = bytesAvailable();
153  }
154 
155  TQByteArray data(size);
156  KSocketAddress address;
157 
158  // now do the reading
159  size = tqreadBlock(data.data(), size, address);
160  if (size < 0)
161  // error has been set
162  return KDatagramPacket();
163 
164  data.resize(size); // just to be sure
165  return KDatagramPacket(data, address);
166 }
167 
168 TQ_LONG KDatagramSocket::send(const KDatagramPacket& packet)
169 {
170  return tqwriteBlock(packet.data(), packet.size(), packet.address());
171 }
172 
173 TQ_LONG KDatagramSocket::tqwriteBlock(const char *data, TQ_ULONG len, const KSocketAddress& to)
174 {
175  if (to.family() != AF_UNSPEC)
176  {
177  // make sure the socket is open at this point
178  if (!socketDevice()->isOpen())
179  // error handling will happen below
180  socketDevice()->create(to.family(), SOCK_DGRAM, 0);
181  }
182  return KClientSocketBase::tqwriteBlock(data, len, to);
183 }
184 
185 void KDatagramSocket::lookupFinishedLocal()
186 {
187  // bind lookup has finished and succeeded
188  // state() == HostFound
189 
190  if (!doBind())
191  return; // failed binding
192 
193  if (peerResults().count() > 0)
194  {
195  setState(Connecting);
196  emit stateChanged(Connecting);
197 
198  lookupFinishedPeer();
199  }
200 }
201 
202 void KDatagramSocket::lookupFinishedPeer()
203 {
204  // this function is called by lookupFinishedLocal above
205  // and is also connected to a signal
206  // so it might be called twice.
207 
208  if (state() != Connecting)
209  return;
210 
211  if (peerResults().count() == 0)
212  {
213  setState(Unconnected);
214  emit stateChanged(Unconnected);
215  return;
216  }
217 
218  KResolverResults::ConstIterator it = peerResults().begin();
219  for ( ; it != peerResults().end(); ++it)
220  if (connect(*it))
221  {
222  // weee, we connected
223 
224  setState(Connected); // this sets up signals
225  //setupSignals(); // setState sets up the signals
226 
227  emit stateChanged(Connected);
228  emit connected(*it);
229  return;
230  }
231 
232  // no connection
233  copyError();
234  setState(Unconnected);
235  emit stateChanged(Unconnected);
236  emit gotError(error());
237 }
238 
239 bool KDatagramSocket::doBind()
240 {
241  if (localResults().count() == 0)
242  return true;
243  if (state() >= Bound)
244  return true; // already bound
245 
246  KResolverResults::ConstIterator it = localResults().begin();
247  for ( ; it != localResults().end(); ++it)
248  if (bind(*it))
249  {
250  // bound
251  setupSignals();
252  return true;
253  }
254 
255  // not bound
256  // no need to set state since it can only be HostFound already
257  copyError();
258  emit gotError(error());
259  return false;
260 }
261 
262 void KDatagramSocket::setupSignals()
263 {
264  TQSocketNotifier *n = socketDevice()->readNotifier();
265  if (n)
266  {
267  n->setEnabled(emitsReadyRead());
268  TQObject::connect(n, TQT_SIGNAL(activated(int)), this, TQT_SLOT(slotReadActivity()));
269  }
270  else
271  return;
272 
273  n = socketDevice()->writeNotifier();
274  if (n)
275  {
276  n->setEnabled(emitsReadyWrite());
277  TQObject::connect(n, TQT_SIGNAL(activated(int)), this, TQT_SLOT(slotWriteActivity()));
278  }
279  else
280  return;
281 }
282 
283 #include "kdatagramsocket.moc"

kdecore

Skip menu "kdecore"
  • Main Page
  • Modules
  • Namespace List
  • Class Hierarchy
  • Alphabetical List
  • Class List
  • File List
  • Namespace Members
  • Class Members
  • Related Pages

kdecore

Skip menu "kdecore"
  • arts
  • dcop
  • dnssd
  • interfaces
  •     interface
  •     library
  •   kspeech
  •   ktexteditor
  • kabc
  • kate
  • kcmshell
  • kdecore
  • kded
  • kdefx
  • kdeprint
  • kdesu
  • kdeui
  • kdoctools
  • khtml
  • kimgio
  • kinit
  • kio
  •   bookmarks
  •   httpfilter
  •   kfile
  •   kio
  •   kioexec
  •   kpasswdserver
  •   kssl
  • kioslave
  •   http
  • kjs
  • kmdi
  •   kmdi
  • knewstuff
  • kparts
  • krandr
  • kresources
  • kspell2
  • kunittest
  • kutils
  • kwallet
  • libkmid
  • libkscreensaver
Generated for kdecore by doxygen 1.8.3.1
This website is maintained by Timothy Pearson.
KDE® and the K Desktop Environment® logo are registered trademarks of KDE e.V. |