C# Client  0.0.0.7
C# Library to interface with Corelink
CorelinkUDP.cs
Go to the documentation of this file.
1 using System;
2 using System.Collections.Generic;
3 using System.Net;
4 using System.Net.Sockets;
5 using System.Text;
6 using System.Threading;
7 using UnityEngine;
8 
9 namespace CoreLink
10 {
14  public class CorelinkUDP
15  {
16  private UdpClient udpClient;
17  private int udpPort;
18  private Thread udpThread;
19  private bool active;
20  private string ControlIP;
21  private List<uint> allowedStreams;
22  private List<ReceiverStreamParams> receiverStreams;
31  public CorelinkUDP(string ControlIP, int udpPort,
32  ref List<uint> allowedStreams, ref List<ReceiverStreamParams> receiverStreams)
33  {
34  this.allowedStreams = allowedStreams;
35  this.receiverStreams = receiverStreams;
36  this.active = true;
37  this.ControlIP = ControlIP;
38  this.udpPort = udpPort;
39  udpClient = new UdpClient(ControlIP, udpPort);
41  }
42 
43 
47  #region [Receiver]
48 
52  public void startUDPListenThread()
53  {
54  udpThread = new Thread(listenForUDPData);
55  udpThread.Start();
56  }
57 
63  void listenForUDPData()
64  {
65  IPEndPoint ep = new IPEndPoint(IPAddress.Parse(ControlIP), udpPort);
66  Debug.Log("Opening UDP Connection" + ep);
67 
68  UdpState state = new UdpState(ep, udpClient);
69 
70  udpClient.BeginReceive(new AsyncCallback(UDPReceiveCallback), state);
71  // idle time to check if the application quits
72  while (active)
73  {
74  Thread.Sleep(100);
75  }
76 
77  Debug.Log("Closing UDP Connection");
78  udpClient.Close();
79  }
85  void UDPReceiveCallback(IAsyncResult ar)
86  {
87  if (!active)
88  {
89  return;
90  }
91  UdpClient c = ((UdpState)(ar.AsyncState)).c;
92  IPEndPoint e = ((UdpState)(ar.AsyncState)).e;
93  byte[] buf = udpClient.EndReceive(ar, ref e);
94 
95  parseUDPMessage(buf);
96  UdpState state = new UdpState(e, c);
97  udpClient.BeginReceive(new AsyncCallback(UDPReceiveCallback), state);
98  }
99 
106  void parseUDPMessage(byte[] udpBuf)
107  {
108  int headerSize = BitConverter.ToUInt16(udpBuf, 0);
109  int dataSize = (int)BitConverter.ToUInt16(udpBuf, 2);
110  uint streamID = (uint)BitConverter.ToUInt16(udpBuf, 4);
111  int federationID = (int)BitConverter.ToUInt16(udpBuf, 6); // Unused for now
112  if (dataSize == 0)
113  return;
114 
115  byte[] header = new byte[headerSize];
116  if (headerSize != 0)
117  {
118  Buffer.BlockCopy(udpBuf, 8, header, 0, headerSize);
119  }
120  byte[] msg = new byte[dataSize];
121  Buffer.BlockCopy(udpBuf, 8 + headerSize, msg, 0, dataSize);
122  // SimpleJSON.JSONNode root = SimpleJSON.JSON.Parse(Encoding.ASCII.GetString(header));
123 
124  if (allowedStreams.Contains(streamID))
125  {
126  for (int i = 0; i < receiverStreams.Count; i++)
127  {
128  if (receiverStreams[i].streamIDs.Contains(streamID))
129  {
130  receiverStreams[i].ReceiverStream.OnMessage(streamID, header, msg);
131  }
132  }
133  }
134  }
135 
141  public void receiverPing(uint streamID)
142  {
143  int num = 0;
144  byte[] numByte = BitConverter.GetBytes(num);
145  byte[] UDPInitMsg = constructUDPMsg(streamID, new byte[0], numByte);
146  udpClient.Send(UDPInitMsg, UDPInitMsg.Length);
147 
148  Debug.Log("Sent empty receiver packet");
149  }
150  #endregion
151 
155  #region [Sender]
156  public void send(uint streamID, byte[] header, byte[] data)
163  {
164  if (udpClient == null) throw new Exception("udpClient undefined");
165 
166  try
167  {
168  byte[] UDPInitMsg = constructUDPMsg(streamID, header, data);
169  udpClient.Send(UDPInitMsg, UDPInitMsg.Length);
170  }
171  catch (SocketException socketException)
172  {
173  Debug.LogException(socketException);
174  throw new Exception("Socket exception: " + socketException);
175  }
176  }
177 
185  byte[] constructUDPMsg(uint streamID, byte[] header, byte[] data)
186  {
187  byte[] dataPacket = new byte[8 + header.Length + data.Length];
188 
189  byte[] headerLengthBytes = BitConverter.GetBytes((ushort)header.Length);
190  // TODO: Check to make sure this will return 2 bytes if size is 0
191  dataPacket[0] = headerLengthBytes[0];
192  dataPacket[1] = headerLengthBytes[1];
193 
194  byte[] dataLengthBytes = BitConverter.GetBytes((ushort)data.Length);
195  dataPacket[2] = dataLengthBytes[0];
196  dataPacket[3] = dataLengthBytes[1];
197 
198  // TODO: Not entirely sure why we cast to ushort
199  byte[] streamIDBytes = BitConverter.GetBytes((ushort)streamID);
200  dataPacket[4] = streamIDBytes[0];
201  dataPacket[5] = streamIDBytes[1];
202 
203  // TODO: Hardcoding federation ID 0 for now
204  dataPacket[6] = 0;
205  dataPacket[7] = 0;
206 
207  if (header.Length > 0)
208  {
209  string headerStr = JsonUtility.ToJson(header);
210  byte[] headerByte = Encoding.ASCII.GetBytes(headerStr);
211  Buffer.BlockCopy(headerByte, 0, dataPacket, 8, headerByte.Length);
212  }
213 
214  Buffer.BlockCopy(data, 0, dataPacket, 8 + header.Length, data.Length);
215 
216  return dataPacket;
217  }
218 
219  #endregion
220  public void stopConnection()
224  {
225  active = false;
226  }
227  }
228 }