static Task C2S2Async(Stream stream, byte[] randomBytes, CancellationTokenSource cts, Timer timer) { timer.Change(Timeout.Infinite, Timeout.Infinite); var s2 = new RtmpHandshake() { Time = (uint)Environment.TickCount, Time2 = 0, Random = randomBytes }; //c2 Task.WaitAll(new Task[] { Task.Factory.StartNew(() => { RtmpHandshake.Read(stream, false); }) }, 3000); //s2 timer.Change(SendTimeout, Timeout.Infinite); return(RtmpHandshake.WriteAsync(stream, s2, false, cts.Token)); }
static Task WriteAsync(Stream stream, RtmpHandshake h, bool writeVersion, CancellationToken ct) { using (var memoryStream = new MemoryStream()) using (var writer = new AmfWriter(memoryStream, null)) { if (writeVersion) { writer.WriteByte(h.Version); } writer.WriteUInt32(h.Time); writer.WriteUInt32(h.Time2); writer.WriteBytes(h.Random); var buffer = memoryStream.ToArray(); return(stream.WriteAsync(buffer, 0, buffer.Length, ct)); } }
async void acceptCallback(IAsyncResult ar) { Socket listener = (Socket)ar.AsyncState; Socket handler = listener.EndAccept(ar); handler.NoDelay = true; // Signal the main thread to continue. _manualResetEvent.Set(); try { await RtmpHandshake.HandshakeAsync(this, handler, this.GetNewClientId(), this.Certificate); } catch (TimeoutException) { handler.Close(); } catch (AuthenticationException) { handler.Close(); throw; } }
static void C2S2(Stream stream) { RtmpHandshake.Read(stream, false); }
/// <summary> /// rtmp握手逻辑 /// HandshakeAsync2 /// c01->s01->s2->c2 /// </summary> /// <param name="server"></param> /// <param name="client_socket"></param> /// <param name="client_id"></param> /// <param name="cert"></param> /// <returns></returns> public static async Task <int> HandshakeAsync(RtmpServer server, Socket client_socket, ushort client_id, X509Certificate2 cert = null) { Stream stream; if (cert != null) { var temp_stream = new SslStream(new NetworkStream(client_socket)); try { await temp_stream.AuthenticateAsServerAsync(cert); } catch (AuthenticationException) { temp_stream.Close(); throw; } stream = temp_stream; } else { stream = new NetworkStream(client_socket); } var random = new Random(Environment.TickCount); var randomBytes = new byte[1528]; random.NextBytes(randomBytes); client_socket.NoDelay = true; CancellationTokenSource cts = new CancellationTokenSource(); //over time cancel task Timer timer = new Timer((s) => { cts.Cancel(); throw new TimeoutException("rtmp 握手已超时!"); }, null, ReceiveTimeout, Timeout.Infinite); //read c0 c1 var c01 = await RtmpHandshake.ReadAsync(stream, true, cts.Token); timer.Change(Timeout.Infinite, Timeout.Infinite); //write s0 s1 var s01 = new RtmpHandshake() { Version = 3, Time = (uint)Environment.TickCount, Time2 = 0, Random = randomBytes }; timer.Change(ReceiveTimeout, Timeout.Infinite); await RtmpHandshake.WriteAsync(stream, s01, true, cts.Token); //write s2 random.NextBytes(randomBytes); await C2S2Async(stream, randomBytes, cts, timer); timer.Change(Timeout.Infinite, Timeout.Infinite); // handshake check //if (!c0.Random.SequenceEqual(s2.Random)) //throw new ProtocolViolationException(); var connect = new RtmpConnect(client_socket, stream, server, client_id, server.Context, server.AmfEncoding, true); connect.ChannelDataReceived += server.SendDataHandler; server.ClientSessions.Add(client_id, new ClientSession() { Connect = connect, LastPing = DateTime.UtcNow, ReaderTask = null, WriterTask = null }); return(client_id); }