summaryrefslogtreecommitdiffstats
path: root/tdecore/kextsock.h
blob: 3b3018b594b0606cb2ebf3622a97e9f84938ae33 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
/*
 *  This file is part of the KDE libraries
 *  Copyright (C) 2000-2004 Thiago Macieira <thiago.macieira@kdemail.net>
 *
 *  This library is free software; you can redistribute it and/or
 *  modify it under the terms of the GNU Library General Public
 *  License as published by the Free Software Foundation; either
 *  version 2 of the License, or (at your option) any later version.
 *
 *  This library is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *  Library General Public License for more details.
 *
 *  You should have received a copy of the GNU Library General Public License
 *  along with this library; see the file COPYING.LIB.  If not, write to
 *  the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
 *  Boston, MA 02110-1301, USA.
 */
#ifndef KEXTSOCK_H
#define KEXTSOCK_H

#include "tdelibs_export.h"

#ifdef Q_OS_UNIX

#include <sys/time.h>

#include <tqstring.h>
#include <tqptrlist.h>
#include <tqiodevice.h>

#include "kbufferedio.h"
#include "ksockaddr.h"

/* External reference to netdb.h */
struct addrinfo;
struct kde_addrinfo;
class KAddressInfo;		/* our abstraction of it */
class TQSocketNotifier;

/*
 * This is extending TQIODevice's error codes
 *
 * According to tqiodevice.h, the last error is IO_UnspecifiedError
 * These errors will never occur in functions declared in TQIODevice
 * (except open, but you shouldn't call open)
 */
#define IO_ListenError		(IO_UnspecifiedError+1)
#define IO_AcceptError		(IO_UnspecifiedError+2)
#define IO_LookupError		(IO_UnspecifiedError+3)

class KExtendedSocketPrivate;
/**
 * The extended socket class.
 *
 * This class should be used instead of TDESocket whenever the user needs
 * fine-grained control over the socket being created. Unlike TDESocket, which
 * does everything at once, without much intervention, KExtendedSocket allows
 * intervention at every step of the process and the setting of parameters.
 *
 * This class allows for the creation of both server and client sockets. The
 * only difference is that the passiveSocket flag must be passed either to
 * the constructor or to setSocketFlags(). If passiveSocket is used, the class will
 * enable functions listen() and accept() and related signals, and will
 * also disable readBlock() and writeBlock().
 *
 * To create a Unix socket, one would pass flag unixSocket to the constructor
 * or setSocketFlags(). The hostname and service/port can be set to whatever is
 * necessary. If no hostname is given, but a service/port is, the socket created
 * will be implementation dependant (usually in /tmp). In any other case, the
 * fields will be concatenated.
 *
 * To create an Internet socket, inetSocket flag can be used. If, on the other
 * hand a specific IP protocol is desired, ipv4Socket and/or ipv6Socket can be
 * used.
 *
 * Note that the socket type selection flags are cumulative. One could select
 * Unix and Internet sockets by using unixSocket | inetSocket. Or, for instance,
 * to make sure only IPv4 and IPv6 sockets are selected, even if future implementations
 * support newer IP protocols, ipv4Socket | ipv6Socket is your guy.
 *
 * @deprecated
 *	This class is now deprecated. Please use the classes in KNetwork for
 *	new programs. In particular, this class is replaced by KNetwork::KStreamSocket
 *	and @ref KNetwork::TDEServerSocket.
 *
 * @author Thiago Macieira <thiago.macieira@kdemail.net>
 * @short an extended socket
 */
class TDECORE_EXPORT KExtendedSocket: public TDEBufferedIO // public TQObject, public TQIODevice
{
  TQ_OBJECT
  

public:
  /**
   * flags that can be passed down to the member functions
   */
  enum Flags
  {
    /* socket address families */
    /*
     * NOTE: if you change this, you have to change function valid_socket() as well
     * These values are hard coded!
     */
    anySocket = 0x00,
    knownSocket = 0x01,
    unixSocket = knownSocket | 0x02,
    inetSocket = knownSocket | 0x04,
    ipv4Socket = inetSocket | 0x100,
    ipv6Socket = inetSocket | 0x200,

    passiveSocket = 0x1000,	/* passive socket (i.e., one that accepts connections) */
    canonName = 0x2000,		/* request that the canon name be found */
    noResolve = 0x4000,		/* do not attempt to resolve, treat as numeric host */

    streamSocket = 0x8000,	/* request a streaming socket (e.g., TCP) */
    datagramSocket = 0x10000,	/* request a datagram socket (e.g., UDP) */
    rawSocket = 0x20000,	/* request a raw socket. This probably requires privileges */

    inputBufferedSocket = 0x200000, /* buffer input in this socket */
    outputBufferedSocket = 0x400000, /* buffer output in this socket */
    bufferedSocket = 0x600000	/* make this a fully buffered socket */
  };

  /**
   * status of the class
   * The status are sequential. If a change to one status is requested,
   * all the prior status will be passed and their actions, performed
   */
  enum SockStatus
  {
    // the numbers are scattered so that we leave room for future expansion
    error = -1,			// invalid status!

    nothing = 0,		// no status, the class has just been created

    lookupInProgress = 50,	// lookup is in progress. Signals will be sent
    lookupDone = 70,		// lookup has been done. Flags cannot be changed
				// from this point on

    created = 100,		// ::socket() has been called, a socket exists
    bound = 140,		// socket has been bound

    connecting = 200,		// socket is connecting (not passiveSocket)
    connected = 220,		// socket has connected (not passiveSocket)

    listening = 200,		// socket is listening (passiveSocket)
    accepting = 220,		// socket is accepting (passiveSocket)

    closing = 350,		// socket is closing (delayed close)

    done = 400			// socket has been closed
  };

public:
  /**
   * Creates an empty KExtendedSocket.
   */
  KExtendedSocket();

  /**
   * Creates a socket with the given hostname and port.
   *
   * If this is a connecting (active) socket, the hostname and port specify
   * the remote address to which we will connect.
   *
   * If this is a listening (passive) socket, the hostname and port specify
   * the address to listen on. In order to listen on every interface
   * available on this node, set @p host to TQString::null. To let the operating
   * system select a port, set it to 0.
   *
   * @sa setAddress
   * @param host	the hostname
   * @param port	the port number
   * @param flags	flags
   */
  KExtendedSocket(const TQString& host, int port, int flags = 0);

  /**
   * Creates a socket with the given hostname and service.
   *
   * If this is a connecting (active) socket, the hostname and service specify
   * the remote address to which we will connect.
   *
   * If this is a listening (passive) socket, the hostname and service specify
   * the address to listen on. In order to listen on every interface
   * available on this node, set @p host to TQString::null. To let the operating
   * system select a port, set the service to "0".
   *
   * @sa setAddress
   * @param host	the hostname
   * @param service	the service
   * @param flags	flags
   */
  KExtendedSocket(const TQString& host, const TQString& service, int flags = 0);

  /**
   * Destroys the socket, disconnecting if still connected and
   * freeing any related resources still being kept.
   */
  virtual ~KExtendedSocket();

  /**
   * Resets the socket, disconnecting if still connected and
   * freeing any related resources still being kept.
   * @since 3.1
   */
  void reset();

  /*
   * --- status, flags and internal variables --- *
   */

  /**
   * Returns the class status.
   * @return the class status
   * @see ::SockStatus
   */
  int socketStatus() const;

  /**
   * Returns the related system error code
   * Except for IO_LookupError errors, these are codes found in
   * errno
   * @return the system error code
   */
  int systemError() const;

  /**
   * Sets the given flags.
   * @param flags	the flags to be set
   * @return the new flags status, or -1 if flags can no longer be set
   */
  int setSocketFlags(int flags);

  /**
   * Returns the current flags
   * @return the current flags
   * @see ::Flags
   */
  int socketFlags() const;

  /**
   * Sets the hostname to the given value. 
   *
   * If this is a listening (passive) socket, the hostname is the host to which the socket
   * will bind in order to listen. If you want to listen in every interface, set it
   * to "*" or TQString::null.
   *
   * If this is a connecting (active) socket, the hostname is the host to which we will try
   * to connect.
   *
   * @param host	the hostname
   * @return true on success, false on error
   */
  bool setHost(const TQString& host);

  /**
   * Returns the hostname.
   * @return the hostname or TQString::null if no host has been set
   */
  TQString host() const;

  /**
   * Sets the port/service.
   * @param port	the port
   */
  bool setPort(int port);

  /**
   * Sets the port/service.
   *
   * In the case of Unix-domain sockets, the port is the filename for the socket.
   * If the name is not an absolute path, "/tmp/" will be prepended.
   *
   * @param port	the port
   * @return true if successful, false on error (e.g. connection already established)
   */
  bool setPort(const TQString& port);

  /**
   * Returns the port/service. If it is a port, the string contains a number.
   * @return the port or TQString::null if it has not been set.
   */
  TQString port() const;

  /**
   * Sets the address where we will connect to.
   *
   * See @ref setHost and @ref setPort for information on the parameters.
   *
   * @param host	the hostname
   * @param port	port number
   * @return true if successful, false on error (e.g. connection already established)
   */
  bool setAddress(const TQString& host, int port);

  /**
   * Sets the address where we will connect to.
   *
   * See @ref setHost and @ref setPort for information on the parameters.
   *
   * @param host	the hostname
   * @param serv	the service
   * @return true if successful, false on error (e.g. connection already established)
   */
  bool setAddress(const TQString& host, const TQString& serv);

  /**
   * Sets the hostname to which we will bind locally before connecting.
   * @param host	the hostname
   * @return false if this is a passiveSocket, otherwise true.
   */
  bool setBindHost(const TQString& host);

  /**
   * Unsets the bind hostname. That is, don't request a binding host.
   * @return true if successful, false on error (e.g. connection already established)
   */
  bool unsetBindHost();

  /**
   * Returns the hostname to which the socket will be/is bound.
   * @return the host or TQString::null if it has not been set.
   */
  TQString bindHost() const;

  /**
   * Sets the port/service to which we will bind before connecting
   * @param port	the port number
   * @return true if successful, false on error (e.g. connection already established)
   */
  bool setBindPort(int port);

  /**
   * Sets the port/service to which we will bind before connecting.
   * @param service	the port number or service name
   * @return true if successful, false on error (e.g. connection already established)
   */
  bool setBindPort(const TQString& service);

  /**
   * Unsets the bind port/service.
   * @return true if successful, false on error (e.g. connection already established)
   */
  bool unsetBindPort();

  /**
   * Returns the service to which the socket will be/is bound.
   * @return the host or TQString::null if it has not been set.
   */
  TQString bindPort() const;

  /**
   * Sets both host and port to which we will bind the socket. Will return
   * false if this is a passiveSocket.
   * @param host	the hostname
   * @param port	the port number
   * @return true if successful, false on error (e.g. connection already established)
   */
  bool setBindAddress(const TQString& host, int port);

  /**
   * Sets both host and service to which we will bind the socket. Will return
   * false if this is a passiveSocket.
   * @param host	the hostname
   * @param service	the service
   * @return true if successful, false on error (e.g. connection already established)
   */
  bool setBindAddress(const TQString& host, const TQString& service);

  /**
   * Unsets the bind address for the socket. That means that we won't
   * attempt to bind to an address before connecting.
   * @return true if successful, false on error (e.g. connection already established)
   */
  bool unsetBindAddress();

  /**
   * Sets the timeout value for the connection (if this is not passiveSocket) or
   * acception (if it is). In the event the given function
   * (connect or accept) returns due to time out, it's possible to call it again.
   *
   * Setting the timeout to 0 disables the timeout feature.
   *
   * @param secs	the timeout length, in seconds
   * @param usecs	the timeout complement, in microseconds
   * @return false if setting timeout makes no sense in the context.
   */
  bool setTimeout(int secs, int usecs = 0);

  /**
   * Returns the timeout value for the connection.
   * @return the timeout value. 0 if there is no timeout.
   */
  timeval timeout() const;

  /**
   * Sets/unsets blocking mode for the socket. When non-blocking mode is enabled,
   * I/O operations might return error and set errno to EWOULDBLOCK. Also,
   * it's not recommended to use this when using the class signals.
   *
   * @param enable	if true, set blocking mode. False, non-blocking mode.
   * @return false on error.
   */
  bool setBlockingMode(bool enable);

  /**
   * Returns the current blocking mode for this socket.
   * @return true if in blocking mode
   */
  bool blockingMode();

  /**
   * Sets/unsets address reusing flag for this socket.
   *
   * This function returns true if the value was set correctly. That is NOT
   * the result of the set.
   * @param enable	if true, set address reusable
   * @return true on success, false on failure. If the socket was not yet created,
   * the value is only remembered. In this case the return value is always true.
   */
  bool setAddressReusable(bool enable);

  /**
   * Returns whether this socket's address can be reused
   * @return true if the address can be reused
   */
  bool addressReusable();

  /**
   * Sets/unsets the v6-only flag for IPv6 sockets.
   *
   * When an IPv6 socket is in use, communication with IPv4 sockets is
   * guaranteed by translating those IPv4 addresses into IPv6 ones
   * (specifically, the v4-mapped addresses). This flag allows that
   * behavior to be turned on and off.
   *
   * Note that this does not have any effect on sockets that are not
   * IPv6 and the function will always return false in those cases.
   * Also note that this flag defaults to off in order to accommodate
   * existing applications.
   *
   * @param enable	if true, no IPv4 translation will be performed;
   *			this socket will be restricted to IPv6 communication
   * @returns true on success, false on failure.
   * @see localAddress to find out if this is an IPv6 socket
   */
  bool setIPv6Only(bool enable);

  /**
   * Returns the status of the v6-only flag for IPv6 sockets.
   * @returns true if the flag is set to on; false if it is not. If this
   * socket is not an IPv6 one, the return value is false.
   * @see setIPv6Only
   */
  bool isIPv6Only();

  /**
   * Sets the buffer sizes for this socket.
   *
   * This implementation allows any size for both parameters. The value given
   * will be interpreted as the maximum size allowed for the buffers, after
   * which the I/O functions will stop buffering. The value of -1 will be
   * interpreted as "unlimited" size. The value of -2 means "no change".
   *
   * Note: changing the buffer size to 0 for any buffer will cause the given
   * buffer's to be discarded. Likewise, setting the size to a value less than
   * the current size will cause the buffer to be shrunk to the wanted value,
   * as if the data had been read.
   * @param rsize	read buffer size
   * @param wsize	write buffer size
   * @return true on success, false if this is not possible in this state (e.g. connection
   *         not established yet)
   */
  virtual bool setBufferSize(int rsize, int wsize = -2);

  /**
   * Returns the local socket address
   * @return the local socket address, can be 0 if the connection has not been established
   *         yet
   */
  const ::TDESocketAddress *localAddress();

  /**
   * Returns the peer socket address. Use KExtendedSocket::resolve() to
   * resolve this to a human-readable hostname/service or port.
   * @return the peer address, can be 0 if the connection has not been established yet
   *         or the socket is passive
   */
  const ::TDESocketAddress *peerAddress();

  /**
   * Returns the file descriptor
   * @return the file descriptor. -1 if there is no fd yet.
   */
  inline int fd() const
  { return sockfd; }

  /*
   * -- socket creation -- *
   */

  /**
   * Performs lookup on the addresses we were given before.
   *
   * This will perform lookups on the bind addresses if they were given.
   * @return 0 or an error. Do not rely on the values returned by lookup
   * as of now. They are not specified.
   */
  virtual int lookup();

  /**
   * Starts an asynchronous lookup for the addresses given.
   *
   * When the lookup is done, the lookupReady signal will be emitted.
   *
   * Note that, depending on the parameters for the lookup, this function might
   * know the results without the need for blocking or queuing an
   * asynchronous lookup. That means that the lookupReady signal might be
   * emitted by this function, so your code should be prepared for that.
   *
   * One such case is when noResolve flag is set.
   * If this function is able to determine the results without queuing
   * and the lookup failed, this function will return -1.
   *
   * @return 0 on success or -1 on error. Note that
   * returning 0 means that either we are in the process of doing
   * lookup or that it has finished already.
   */
  virtual int startAsyncLookup();

  /**
   * Cancels any on-going asynchronous lookups
   */
  virtual void cancelAsyncLookup();

  /**
   * Place the socket in listen mode. The parameters are the same as for
   * the system listen() call.
   * @param N		the queue length for pending connections
   * @return 0 on success, -1 on system error (errno
   *         available) and -2 if this is not a passiveSocket.
   */
  virtual int listen(int N = 5); // 5 is arbitrary

  /**
   * Accepts an incoming connection from the socket. If this socket is in
   * blocking mode, this function will block until a connection is received.
   * Otherwise, it might return with error. The sock parameter will be
   * initialised with the newly created socket.
   *
   * Upon successful acception (i.e., this function returns 0), the newly
   * created socket will be already connected. The socket will be unbuffered
   * and readyRead() and readyWrite() signals will be disabled.
   *
   * @param sock	a pointer to an KExtendedSocket variable
   * @return 0 on success, -1 on system error (errno set) and -2 if this is
   * not a passiveSocket and -3 if this took too long (time out)
   */
  virtual int accept(KExtendedSocket *&sock);

  /**
   * Attempts to connect to the remote host.
   * After successful connection (return value 0), the socket will be ready
   * for I/O operations. Note, however, that not all signals may be enabled
   * for emission by this socket:
   * @li readyRead and readyWrite signals will be enabled only if
   * enableRead or enableWrite were called. You can still enable
   *    them by calling those functions, of course.
   * @li #closed() will only be sent if we are indeed reading from the input
   *    stream. That is, if this socket is buffering the input. See setBufferSize
   *
   * Note that, in general, functions inherited/overridden from TDEBufferedIO will only
   * work on buffered sockets, like bytesAvailable and bytesToWrite.
   * @return    The return values are:
   * @li 0: success
   * @li -1: system error, errno was set accordingly
   * @li -2: this socket cannot connect(); this is a passiveSocket. It can also
   *   mean that the function was unable to make a connection with the given
   *   bind address or that an asynchronous connection attempt is already
   *   in progress.
   * @li -3: connection timed out
   *
   */
  virtual int connect();

  /**
   * Starts an asynchronous connect. This works exactly the same as #connect,
   * except that the connection result won't be returned.
   *
   * Note that those signals might be emitted before this function returns, so your
   * code should be prepared for that condition.
   *
   * You must call cancelAsyncConnect() before you delete the socket if you
   * call this.  Otherwise you will have crashes.
   *
   * @return 0 on successful queuing of the connect or -1 on error.
   *         If this function returns 0, then the connectionSuccess() or the
   * connectionFailed() signals will be emitted.
   */
  virtual int startAsyncConnect();

  /**
   * Cancels any on-going asynchronous connection attempt.
   */
  virtual void cancelAsyncConnect();

  /**
   * Implementation of TQIODevice::open() pure virtual function.
   * This depends on the target host address already being there.
   * If this is a passiveSocket, this is identical to call listen(); else, if
   * this is not a passiveSocket and no connection attempt is in progress, this
   * is like connect(). If one is in progress, this function will fail.
   * @param mode the open mode. Must be IO_Raw | IO_ReadWrite
   * @return true if successful, false when an error occurred or the most was
   *         not correct
   */
  virtual bool open(int mode = (int)(IO_Raw | IO_ReadWrite));

  /**
   * Closes the socket. If we have data still in the write buffer yet to be
   * sent, the socket won't be closed right now. It'll be closed after we managed
   * to send everything out.
   * If you want to close the socket now, you may want to call flush() first,
   * and then closeNow().
   */
  virtual void close();

  /**
   * Closes the socket now, discarding the contents of the write buffer, if any.
   * The read buffer's contents are kept until they are emptied by read operations
   * or the class is destroyed.
   */
  virtual void closeNow();

  /**
   * Releases the socket and anything we have holding on it. The class cannot
   * be used anymore. In other words, this is just like closeNow(), but it does
   * not actually close the socket.
   *
   * This is useful if you just want to connect and don't need the rest of the
   * class.
   *
   * Note that the buffers' contents will be discarded.
   *
   * Use of this method is discouraged, because the socket created might be such that
   * normal library routines can't handle (read, write, close, etc.)
   */
  virtual void release();

  /*
   * -- I/O --
   */

  /**
   * Flushes the socket buffer. You need not call this method during normal
   * operation as we will try and send everything as soon as possible.
   * However, if you want to make sure that data in the buffer is being sent
   * at this moment, you can call this function. It will try to send as much
   * data as possible, but it will stop as soon as the kernel cannot receive
   * any more data, and would possibly block.
   *
   * By repeatedly calling this function, the behavior will be like that of
   * a blocking socket. Indeed, if this function is called with the kernel not
   * ready to receive data, it will block, unless this is a non-blocking socket.
   *
   * This function does not touch the read buffer. You can empty it by calling
   * readBlock() with a null destination buffer.
   */
  virtual void flush();

  /**
   * Returns length of this socket. This call is not supported on sockets.
   * @return the length of this socket, or 0 if unsupported
   */
  virtual inline TQ_ULONG size() const
  { return 0; }

  /**
   * Returns relative position from start. This call is not supported on sockets.
   * @return the relative position from the start, or 0 if unsupported
   */
  virtual inline TQ_ULONG at() const
  { return 0; }

  /**
   * Returns true if we are at position. This is not supported on sockets.
   * @param i the position to check
   * @return true if we art at the given position, or always true if unsupported.
   */
  virtual inline bool at(int i)
  { Q_UNUSED(i);return true; }

  /**
   * Returns true if we are at the end. This is not supported on sockets, but
   * we always are at the end in a socket...
   * @return true if we are at the end. Always false if unsupported.
   */
  virtual inline bool atEnd() const
  { return false; }

  /**
   * Reads a block of data from the socket.
   *
   * If the socket is not buffered, this function will simply call the underlying
   * read method. This function will block if the socket is not on non-blocking mode
   * (see setBlockingMode) and there is not enough data to be read in the
   * Operating System yet. If we are in non-blocking operation, the call will
   * fail in this case.
   *
   * However, if we are buffering, this function will instead read from the
   * buffer while there is available data. This function will never block
   * in buffering mode, which means that if you try to read while the buffers
   * are empty, this function will always return -1 and set the system error to
   * EWOULDBLOCK (aka EAGAIN), so as to mimic non-blocking operation.
   *
   * @param data	where we will write the read data to
   * @param maxlen	maximum length of data to be read
   * @return the number of bytes effectively read, or a negative number in case
   * or an error. If the @p data param is not null, then this is also the number
   * of bytes copied into that buffer. If the return value is different than
   * @p maxlen, then this function encountered a situation in which no more
   * bytes were available. Subsequent calls might cause this function to one
   * of these behaviours:
   * @li return an error, with EWOULDBLOCK system error, if we buffering
   *   or we are in non-blocking mode
   * @li otherwise, it'll block
   * This function returns 0, if the function detected end-of-file condition
   * (socket was closed)
   */
  virtual TQ_LONG readBlock(char *data, TQ_ULONG maxlen);

  /**
   * Writes a block of data to the socket.
   *
   * If the socket is not buffered, this function will simply call the underlying
   * write method. This means that the function might block if that method blocks
   * as well. That situation is possible if we are not in non-blocking mode and
   * the operating system buffers are full for this socket. If we are in
   * non-blocking mode and the operating system buffers are full, this function
   * will return -1 and the system error will be set to EWOULDBLOCK.
   *
   * If we are buffering, this function will simply transfer the data into the
   * write buffer. This function will then always succeed, as long as there is
   * enough room in the buffer. If the buffer size was limited and that limit
   * is reached, this function will copy no more bytes than that limit. Trying
   * to write with a full buffer will return -1 and set system error to
   * EWOULDBLOCK.
   *
   * @param data	the data to write
   * @param len		the length of data to write
   * @return the number of bytes written from @p data buffer.
   * The return value might be less than @p len if the output buffers cannot
   * accommodate that many bytes and -1 in the case of an errro.
   */
  virtual TQ_LONG writeBlock(const char *data, TQ_ULONG len);

  /**
   * Peeks at a block of data from the socket.
   *
   * This is exactly like read, except that the data won't be flushed from the
   * read buffer.
   *
   * If this socket is not buffered, this function will always return with
   * 0 bytes copied.
   *
   * @param data	where to store the data
   * @param maxlen	how many bytes to copy, at most
   * @return the number of bytes copied. 0 does not mean end-of-file
   *         condition.
   */
  virtual int peekBlock(char *data, uint maxlen);

  /**
   * Reimplementation of unreadBlock() method. This is so because unreading in
   * sockets doesn't make sense, so this function will always return -1 (error)
   * and set the system error to ENOSYS.
   * @return always -1 (error)
   */
  virtual int unreadBlock(const char *data, uint len);

  /**
   * Returns the number of available bytes yet to be read via readBlock
   * and family of functions.
   *
   * Note: as of now, this only works on input-buffered sockets. This will
   * change in the future
   * @return The number of available bytes, or -1 on error or -2 if this call is invalid
   * in the current state.
   */
  virtual int bytesAvailable() const;

  /**
   * Waits @p msec milliseconds for more data to be available (use 0 to
   * wait forever). The return value is the amount of data available for
   * read in the read buffer.
   *
   * @param msec	milliseconds to wait
   * @return -1 in case of system error and -2 in case of invalid socket
   *         state
   */
  virtual int waitForMore(int msec);

  /**
   * Gets a single character (unsigned char) from the stream.
   * @return the value of the character. Negative if there was an error.
   */
  virtual int getch();

  /**
   * Writes a single character (unsigned char) to the stream. All other bits
   * will be ignored.
   * @param ch	character to write, converted to char
   */
  virtual int putch(int ch);

  /**
   * Unreads one character from the stream. This is not possible on sockets.
   * @return always returns -1 on sockets.
   */
  virtual int ungetch(int)
  { return -1; }

  /**
   * Toggles the emission of the readyRead signal.
   *
   * Note that this signal is emitted every time more data is available to be
   * read, so you might get flooded with it being emitted every time, when in
   * non-buffered mode. However, in buffered mode, this signal will be
   * emitted only when there is data coming in from the wire.
   * By default, this flag is set to false, i.e., signal not being emitted.
   * @param enable	if true, the signal will be emitted
   */
  virtual void enableRead(bool enable);

  /**
   * Toggles the emission of the readyWrite signal.
   *
   * Note that this signal is emitted only when the OS is ready to receive more
   * data, which means that the write buffer is empty. And when that is reached,
   * this signal will possibly be emitted on every loop, so you might
   * want to disable it. By default, this flag is set to false.
   * @param enable	if true, the signal will be emitted
   */
  virtual void enableWrite(bool enable);

signals:
  /**
   * This signal is emitted whenever an asynchronous lookup process is done.
   * The parameter @p count tells
   * @param count the number of results
   */
  void lookupFinished(int count);

  /**
   * This signal is emitted whenever we connected asynchronously to a host.
   */
  void connectionSuccess();

  /**
   * This signal is emitted whenever our asynchronous connection attempt
   * failed to all hosts listed.
   * @param error	the errno code of the last connection attempt
   */
  void connectionFailed(int error);

  /**
   * This signal is emitted whenever this socket is ready to accept another
   * socket.
   * @see accept()
   */
  void readyAccept();

protected:
  int sockfd;			// file descriptor of the socket

protected slots:

  void socketActivityRead();
  void socketActivityWrite();
  void dnsResultsReady();
  void startAsyncConnectSlot();
  void connectionEvent();

protected:

  TQSocketNotifier *readNotifier();
  TQSocketNotifier *writeNotifier();

private:

  // protection against accidental use
  KExtendedSocket(KExtendedSocket&);
  KExtendedSocket& operator=(KExtendedSocket&);

  /**
   * This is actually a wrapper around getaddrinfo().
   * @internal
   */
  static int doLookup(const TQString& host, const TQString& serv, addrinfo& hint,
		      kde_addrinfo** result);

protected:
  /**
   * Sets the error code
   */
  void setError(int errorkind, int error);

  inline void cleanError()
  { setError(IO_Ok, 0); }

  /**
   * Sets the socket status. For derived classes only.
   */
  void setSocketStatus(int status);

public:
  /**
   * Performs resolution on the given socket address.
   *
   * That is, tries to resolve the raw form of the socket address into a textual
   * representation.
   *
   * @param sock	the socket address
   * @param len         the length of the socket address
   * @param host	where the hostname will be written
   * @param port	where the service-port will be written
   * @param flags	the same flags as getnameinfo()
   * @returns 0 on success, nonzero otherwise.
   */
  static int resolve(sockaddr* sock, ksocklen_t len, TQString& host, TQString& port, int flags = 0) TDE_DEPRECATED;

  /**
   * Performs resolution on the given socket address.
   *
   * That is, tries to resolve the raw form of the socket address into a textual
   * representation.
   *
   * @param sock	the socket address
   * @param host	where the hostname will be written
   * @param port	where the service-port will be written
   * @param flags	the same flags as getnameinfo()
   * @returns 0 on success, nonzero otherwise.
   */
  static int resolve(::TDESocketAddress* sock, TQString& host, TQString& port, int flags = 0) TDE_DEPRECATED;

  /** @deprecated
   * This function is now deprecated. Please use @ref KNetwork::KResolver::resolve.
   *
   * Performs lookup on the given hostname/port combination and returns a list
   * of matching addresses.
   * The error code can be transformed into string by KExtendedSocket::strError()
   * with code of IO_LookupError.
   *
   * IMPORTANT: the result values of the TQPtrList must be deleted after use. So,
   * if you don't copy the KAddressInfo objects, the best way to assure that
   * is to call setAutoDelete(true) on the list right after this function
   * returns. If you do copy the results out, you must assure that the objects
   * get deleted when they are not needed any more.
   *
   * @param host	the hostname to look up
   * @param port	the port/service to look up
   * @param flags	flags to be used when looking up, Flags
   * @param error	pointer to a variable holding the error code
   * @return a list of KAddressInfos
   */
  static TQPtrList<KAddressInfo> lookup(const TQString& host, const TQString& port, int flags = 0, int *error = 0) TDE_DEPRECATED;

  /**
   * Returns the local socket address
   * Remember to delete the returned object when it is no longer needed.
   * @param fd		the file descriptor
   * @return the local socket address or 0 if an error occurred. Delete after use.
   */
  static ::TDESocketAddress *localAddress(int fd) TDE_DEPRECATED;

  /**
   * Returns the peer socket address. Use KExtendedSocket::resolve() to
   * resolve this to a human-readable hostname/service or port.
   * Remember to delete the returned object when it is no longer needed.
   * @param fd		the file descriptor
   * @return the peer socket address or 0 if an error occurred. Delete after use.
   */
  static ::TDESocketAddress *peerAddress(int fd) TDE_DEPRECATED;

  /**
   * Returns the representing text of this error code
   * @param code	the error code, as seen in status()
   * @param syserr	the system error, as from systemError()
   * @return the text for the given error code
   */
  static TQString strError(int code, int syserr);

  /**
   * Sets/unsets address reusing flag for this socket.
   *
   * This function returns true if the value was set correctly. That is NOT
   * the result of the set.
   * @param fd	the file descriptor
   * @param enable	if true, set address reusable
   * @return true on success, false on failure.
   */
  static bool setAddressReusable(int fd, bool enable) TDE_DEPRECATED;

protected:
  virtual void virtual_hook( int id, void* data );
private:
  KExtendedSocketPrivate *d;

  friend class TDESocket;
  friend class TDEServerSocket;
};

/** @deprecated
 * This class is now deprecated. Please see @ref KNetwork::KResolver for the new API.
 *
 * Contains information about an internet address. It wraps addrinfo,
 * see getaddrinfo(3) for more information.
 */
class TDECORE_EXPORT KAddressInfo
{
private:
  addrinfo *ai;
  ::TDESocketAddress *addr;

  inline KAddressInfo() : ai(0), addr(0)
  { }

  //  KAddressInfo(addrinfo *ai);
  KAddressInfo(KAddressInfo&) { }
  KAddressInfo& operator=(KAddressInfo&) { return *this; }

public:
  ~KAddressInfo();

  /**
   * Returns the KAddressInfo's TDESocketAddress.
   * Only valid as long as the KAddressInfo exists.
   */
  inline TDE_DEPRECATED operator const ::TDESocketAddress*() const 
  { return addr; }

  /**
   * Returns the KAddressInfo's addrinfo.
   */
  inline TDE_DEPRECATED operator const addrinfo&() const
  { return *ai; }

  /**
   * Returns a pointer to KAddressInfo's addrinfo.
   * Only valid as long as the KAddressInfo exists.
   */
  inline TDE_DEPRECATED operator const addrinfo*() const
  { return ai; }

  /**
   * Returns the KAddressInfo's TDESocketAddress.
   * Only valid as long as the KAddressInfo exists.
   * @return the KAddressInfo's TDESocketAddress.
   */
  inline TDE_DEPRECATED const ::TDESocketAddress* address() const
  { return addr; }

  /**
   * Returns the flags of the address info (see getaddrinfo(3)).
   * @return the flags of the addres info.
   */
  int flags() const TDE_DEPRECATED;

  /**
   * Returns the family of the address info (see getaddrinfo(3)).
   * @return the family of the addres info.
   */
  int family() const TDE_DEPRECATED;

  /**
   * Returns the socket type of the address info (see getaddrinfo(3)).
   * @return the socket type of the addres info.
   */
  int socktype() const TDE_DEPRECATED;

  /**
   * Returns the protocol of the address info (see getaddrinfo(3)).
   * @return the protocol of the addres info.
   */
  int protocol() const TDE_DEPRECATED;


  /**
   * Returns the official name of the host (see getaddrinfo(3)).
   * Only valid as long as the KAddressInfo exists.
   * @return the official name of the host
   */
  const char* canonname() const TDE_DEPRECATED;

  /**
   * Returns the length of the TDESocketAddress.
   * @return the TDESocketAddress's length
   */
  inline int length() const
  { if (addr) return addr->size(); return 0; }

  friend class KExtendedSocket;
};

#endif //Q_OS_UNIX

#endif // KEXTSOCK_H