public void RequestAllocate() { if (++turnAllocateCount > 2) { return; } MessageSTUN message = CreateMessageSTUN(STUNMethod.AllocateRequest); //message.WriteString(STUNAttribute.ServerName, "Coturn-4.5.1.1 'dan Eider'"); message.WriteString(STUNAttribute.Username, message.username); message.WriteString(STUNAttribute.Realm, message.realm); //message.WriteString(STUNAttribute.Password, message.password); message.WriteUInt(STUNAttribute.Lifetime, lifeTime); message.WriteEmpty(STUNAttribute.DontFragment); message.WriteUInt(STUNAttribute.RequestedTransport, (uint)(17 << 24));//(uint)(17 << 24) if (nonce != null) { message.WriteBytes(STUNAttribute.Nonce, nonce); message.WriteRequestIntegrity(); } byte[] pkg = message.WriteRequest(); sender.Send(pkg); }
public string GetAttributeKeys(MessageSTUN message) { string attrKeys = ""; foreach (KeyValuePair <STUNAttribute, object> entry in message.response) { string key = Enum.GetName(typeof(STUNAttribute), entry.Key); int id = (int)entry.Key; if (attrKeys.Length > 0) { attrKeys += "\n"; } object value = entry.Value; string valueStr = ""; if (value is string v) { valueStr = v; } else if (value is byte[] b) { valueStr = NetworkSerializer.ByteArrayToHexString(b); } else { valueStr = value.ToString(); } attrKeys += key + "(" + id.ToString("X") + ") = " + valueStr; } return(attrKeys); }
private byte[] AddIndicationHeader(STUNAddress stunAddress, byte[] data) { // send indication MessageSTUN message = CreateMessageSTUN(STUNMethod.DataIndication); byte[] ret; if (stunAddress.IsIPv4) { ret = new byte[8]; ret[1] = (byte)(0x01); // family } else { ret = new byte[16]; ret[1] = (byte)(0x02); // family } ret[0] = (byte)(0x0); ret[3] = (byte)(stunAddress.port & 0xff); ret[2] = (byte)((stunAddress.port >> 8) & 0xff); ret[2] ^= transactionID[0]; ret[3] ^= transactionID[1]; for (int i = 0; i < stunAddress.address.Length; i++) { ret[4 + i] = (byte)(stunAddress.address[i] ^ transactionID[i]); } message.WriteBytes(STUNAttribute.XorPeerAddress, ret); message.WriteEmpty(STUNAttribute.DontFragment); message.WriteBytes(STUNAttribute.Data, data); return(message.WriteRequest()); }
public void RequestChannelBind(STUNAddress stunAddress) { lock (_lock) { MessageSTUN message = CreateMessageSTUN(STUNMethod.ChannelBindRequest); // channel number [0x4000 through 0x4FFF](uint)random.Next(0x4001, 0x4FFF); uint channelNumber; if (!ip2ChannelNumber.ContainsKey(stunAddress.ToString())) { GenerateChannelNumberForPeer(stunAddress); } channelNumber = ip2ChannelNumber[stunAddress.ToString()]; Console.WriteLine("RequestChannelBind: {0} {1}:{2}", channelNumber, stunAddress.ToString(), stunAddress.port); channelNumber = (uint)(channelNumber << 16); message.WriteString(STUNAttribute.Username, message.username); message.WriteString(STUNAttribute.Realm, message.realm); message.WriteUInt(STUNAttribute.ChannelNumber, channelNumber); byte[] ret; if (stunAddress.IsIPv4) { ret = new byte[8]; ret[1] = (byte)(0x01); // family } else { ret = new byte[16]; ret[1] = (byte)(0x02); // family } ret[0] = (byte)(0x0); ret[3] = (byte)(stunAddress.port & 0xff); ret[2] = (byte)((stunAddress.port >> 8) & 0xff); ret[2] ^= transactionID[0]; ret[3] ^= transactionID[1]; for (int i = 0; i < stunAddress.address.Length; i++) { ret[4 + i] = (byte)(stunAddress.address[i] ^ transactionID[i]); } message.WriteBytes(STUNAttribute.XorPeerAddress, ret); if (nonce != null) { message.WriteBytes(STUNAttribute.Nonce, nonce); message.WriteRequestIntegrity(); } byte[] pkg = message.WriteRequest(); sender.Send(pkg); } }
public virtual void OnAllocateResponse(MessageSTUN message) { lock (_lock) { ip2ChannelNumber.Clear(); channelNumber2Peer.Clear(); } GenerateChannelNumberForAllPeers(); RequestRefreshAllBindingChannelLifeTime(); StartRefreshTimer(); StartCheckingConnectionTimer(); STUNAddress sa = (STUNAddress)message.Get(STUNAttribute.XorRelayedAddress); //OnServerDataReceived?.BeginInvoke(this, new STUN_ServerDataReceivedEventArgs((int)responseChannelNumber, new ArraySegment<byte>(appData)), EndAsyncEvent, null); OnAllocateResponseEvent?.Invoke(this, new NATP_SignalingEventArgs(true, "", new IPEndPoint(new IPAddress(sa.address), sa.port))); }
public void RequestRefreshAllocationeLifeTime(uint lifetime) { MessageSTUN message = CreateMessageSTUN(STUNMethod.RefreshRequest); message.WriteString(STUNAttribute.Username, message.username); message.WriteString(STUNAttribute.Realm, message.realm); message.WriteUInt(STUNAttribute.Lifetime, lifetime); //message.WriteUInt(STUNAttribute.RequestedTransport, (uint)(17 << 24)); if (nonce != null) { message.WriteBytes(STUNAttribute.Nonce, nonce); message.WriteRequestIntegrity(); } byte[] pkg = message.WriteRequest(); sender.Send(pkg); }
public void RequestCreatePermission(STUNAddress stunAddress) { lock (_lock) { MessageSTUN message = CreateMessageSTUN(STUNMethod.CreatePermissionRequest); message.WriteString(STUNAttribute.Username, message.username); message.WriteString(STUNAttribute.Realm, message.realm); byte[] ret; if (stunAddress.IsIPv4) { ret = new byte[8]; ret[1] = (byte)(0x01); // family } else { ret = new byte[16]; ret[1] = (byte)(0x02); // family } ret[0] = (byte)(0x0); ushort xorFlag16 = (ushort)(magicCookie >> 16); ret[3] = 0; ret[2] = 0; ret[2] ^= transactionID[0]; ret[3] ^= transactionID[1]; for (int i = 0; i < stunAddress.address.Length; i++) { ret[4 + i] = (byte)(stunAddress.address[i] ^ transactionID[i]); } message.WriteBytes(STUNAttribute.XorPeerAddress, ret); if (nonce != null) { message.WriteBytes(STUNAttribute.Nonce, nonce); message.WriteRequestIntegrity(); } byte[] pkg = message.WriteRequest(); sender.Send(pkg); } }
public virtual void OnChannelBindError(MessageSTUN message) { Start(); }
public virtual void OnAllocateError(MessageSTUN message) { RequestAllocate(); }
public virtual void OnCreatePermissionResponse(MessageSTUN message) { }
public virtual void OnRefreshErrorResponse(MessageSTUN message) { RequestRefreshAllocationeLifeTime(this.lifeTime); RequestRefreshAllBindingChannelLifeTime(); StartRefreshTimer(); }
public virtual void OnRefreshResponse(MessageSTUN message) { OnRefreshLifeTimeResponseEvent?.Invoke(); }
public virtual void OnChannelBindResponse(MessageSTUN message) { }
public virtual void OnBindingResponse(MessageSTUN message) { }
public virtual void OnResponse(byte[] buffer, long offset, long size) { byte[] appData; MessageSTUN message = new MessageSTUN(buffer, offset, size, out appData); if (!message.IsSTUNMessage) // Normal Data Received { string ip; uint responseChannelNumber; if (message.isIndicateData) // sender's ip and channel bind's ip are same, but port are different, so stun server send indicate data { if (!autoUpdatePort) { // deal with it return; } if (ChannelNumberMode) { AddPeer(message.indicateAddress); RequestChannelBind(message.indicateAddress); return; } else { ip = message.indicateAddress.ToString(); if (!ip2ChannelNumber.ContainsKey(ip)) { AddPeer(message.indicateAddress); return; } } responseChannelNumber = ip2ChannelNumber[ip]; } else { responseChannelNumber = message.responseChannelNumber; } if (IsClientHeartbeat(appData)) { SendHeartBeatToClient(responseChannelNumber); } else if (IsClientDisconnectHeartbeat(appData)) { lock (_lockHeartbeat) { peerHeartbeat.Remove(responseChannelNumber); } DisconnectClient(responseChannelNumber); } else { OnServerDataReceived?.Invoke(this, new NATP_STUN_ServerDataReceivedEventArgs((int)responseChannelNumber, new ArraySegment <byte>(appData))); //OnServerDataReceived?.BeginInvoke(this, new STUN_ServerDataReceivedEventArgs((int)responseChannelNumber, new ArraySegment<byte>(appData)), EndAsyncEvent, null); } } else // Is STUN Server response { var newNonce = (byte[])message.Get(STUNAttribute.Nonce); if (newNonce != null) { nonce = newNonce; } switch (message.method) { case STUNMethod.AllocateResponse: OnAllocateResponse(message); break; case STUNMethod.BindingResponse: OnBindingResponse(message); break; case STUNMethod.ChannelBindError: OnChannelBindError(message); break; case STUNMethod.ChannelBindResponse: OnChannelBindResponse(message); break; case STUNMethod.AllocateError: OnAllocateError(message); break; case STUNMethod.RefreshResponse: OnRefreshResponse(message); break; case STUNMethod.RefereshError: OnRefreshErrorResponse(message); break; case STUNMethod.CreatePermissionResponse: OnCreatePermissionResponse(message); break; } } }