Jamoma API  0.6.0.a19
TTNetSocket.h
1 /*
2  * Jamoma Network Socket
3  * Copyright © 2010, Tim Place
4  *
5  * License: This code is licensed under the terms of the "New BSD License"
6  * http://creativecommons.org/licenses/BSD/
7  */
8 
9 #ifndef __TT_NETSOCKET_H__
10 #define __TT_NETSOCKET_H__
11 
12 
13 
14 #ifndef TT_PLATFORM_WIN
15  #include <sys/socket.h>
16  #include <netinet/in.h>
17  #include <netinet/tcp.h>
18  #include <netdb.h>
19  #include <sys/types.h>
20  #include <unistd.h>
21 #else
22  #ifndef WIN32_LEAN_AND_MEAN
23  #define WIN32_LEAN_AND_MEAN
24  #endif
25  #include <winsock2.h>
26  #include <WS2tcpip.h>
27 #endif
28 
29 #include "TTFoundationAPI.h"
30 #include "TTThread.h"
31 
32 
33 
34 
35 
36 /** Our thread worker for receiving packets with this socket. */
37 void* TTNetSocketListener(void* anArgument);
38 void* TTNetSocketReceiver(void* anArgument);
39 
40 
41 class TTNetSocketConnection;
42 typedef TTNetSocketConnection* TTNetSocketConnectionPtr;
43 
44 
45 class TTNetSocket {
46  friend class TTNetSocketConnection;
47 
48  static const int kConnectionBacklogSize = 20; // how many pending connections queue will hold
49  int mSocketDescriptor;
50 
51  addrinfo* mSocketAddressInfo; // You'll load this struct up a bit, and then call getaddrinfo(). It'll return a pointer to a new linked list of these structures filled out with all the goodies you need.
52 
53  TTThreadPtr mSocketListenerThread; /// for receiving data
54  TTList mConnections;
55  TTObjectBasePtr mOwner; ///< The object that instantiated this socket and will receive notifications.
56 
57 public:
58 
59  /** Create a socket for network communication.
60 
61  @param address may be symbolic (www.jamoma.org) or numeric (192.168.1.1).
62  an empty string is interpreted as meaning your own local device's IP address.
63  @param port could be a string with a port number but also could be "http" or "ftp" (etc.)
64  @param transport should be the symbol "udp" or "tcp"
65  */
66  TTNetSocket(const TTObjectBasePtr owner, const TTString& address, const TTString& port, const TTSymbol& transport);
67 
68  ~TTNetSocket()
69  {
70  delete mSocketListenerThread;
71  if (mSocketAddressInfo)
72  freeaddrinfo(mSocketAddressInfo);
73  if (mSocketDescriptor)
74  #ifndef TT_PLATFORM_WIN
75  close(mSocketDescriptor);
76  #else
77  closesocket(mSocketDescriptor);
78  #endif
79 
80  }
81 
82 
83 private:
84  /**
85  associate that socket with a port on your local machine.
86  (This is commonly done if you're going to listen() for incoming connections on a specific port
87 
88 
89 
90  ????? maybe we should just do this automatically if no address is passed in to the constructor ??????
91 
92 
93 
94  */
95  void Bind()
96  {
97  int err;
98 
99  err = bind(mSocketDescriptor, mSocketAddressInfo->ai_addr, mSocketAddressInfo->ai_addrlen);
100  if (err == -1) {
101  TTLogError("TTSocket call to bind() failed! \n");
102  }
103  }
104 
105 
106 public:
107  /** This function is called in the listener thread.
108  Made public so it can be called by a C callback function, but should not be accessed directly by users. */
109  void Accept();
110 
111 
112 private:
113  // for sending, same thoughts and caveats apply here as to Bind()
114  void Connect()
115  {
116  int err;
117 
118  err = connect(mSocketDescriptor, mSocketAddressInfo->ai_addr, mSocketAddressInfo->ai_addrlen);
119  if (err == -1) {
120  TTLogError("TTSocket call to connect() failed! \n");
121  }
122  }
123 
124 public:
125 
126  /** This should work for both udp and tcp, because we called connect.
127  If for udp we do not wish to connect(), then we will need to change the call for udp to use sendto().
128 
129  Also, there is additional work to do if we wish to send OSC.
130  For example, the packets have to be multples of 4 bytes in size.
131  */
132  TTErr Send(const TTString& message)
133  {
134  int result;
135 
136  result = send(mSocketDescriptor, message.c_str(), message.size(), 0);
137  if (result == -1) {
138  TTLogError("TTSocket call to sendto() failed! \n");
139  }
140  else if (result != message.size()) {
141  TTLogError("TTSocket call to sendto() didn't send all of the bytes \n");
142  // only transmitted 'result' number of bytes, need to try again with the rest of the bytes...
143  }
144  return (TTErr)result;
145  }
146 
147 };
148 
149 typedef TTNetSocket* TTNetSocketPtr;
150 
151 
152 
153 class TTNetSocketConnection {
154  static const int kReceiveBufferSize = 65536;
155  char mReceiveBuffer[kReceiveBufferSize];
156  TTNetSocketPtr mSocket;
157  TTThreadPtr mReceiverThread;
158 
159 public:
160 
161  TTNetSocketConnection(TTNetSocketPtr socket) :
162  mSocket(socket)
163  {
164  mReceiverThread = new TTThread(TTNetSocketReceiver, this);
165  }
166 
167 
168  ~TTNetSocketConnection()
169  {
170  delete mReceiverThread;
171  }
172 
173 
174  /** Try to receive data from a connection. */
175  void Receive();
176 
177 };
178 
179 
180 
181 
182 #endif // __TT_NETSOCKET_H__
const char * c_str() const
Return a pointer to the internal C-string.
Definition: TTString.h:83
Base class for all first-class Jamoma objects.
Definition: TTObjectBase.h:109
The TTSymbol class is used to represent a string and efficiently pass and compare that string...
Definition: TTSymbol.h:26
void TTFOUNDATION_EXPORT TTLogError(TTImmutableCString message,...)
Platform and host independent method for posting errors.
Definition: TTBase.cpp:572
TTErr
Jamoma Error Codes Enumeration of error codes that might be returned by any of the TTBlue functions a...
Definition: TTBase.h:342
size_t size() const
Find out the length of a string.
Definition: TTString.h:144
The TTString class is used to represent a string.
Definition: TTString.h:34