private void UploadLegacy() { Debug.WriteLineIf(DccUtil.DccTrace.TraceInfo, "[" + Thread.CurrentThread.Name + "] DccFileSession::UploadLegacy()"); try { int bytesRead = 0; byte[] ack = new byte[4]; while ((bytesRead = dccFileInfo.TransferStream.Read(buffer, 0, buffer.Length)) != 0) { socket.Send(buffer, 0, bytesRead, SocketFlags.None); ResetActivityTimer(); AddBytesProcessed(bytesRead); //Wait for acks from client socket.Receive(ack); } //Some IRC clients need a moment to catch up on their acks if our send buffer //is larger than their receive buffer. Test to make sure they ack all the bytes //before closing. This is only needed in legacy mode. while (!dccFileInfo.AcksFinished(DccUtil.DccBytesToLong(ack))) { socket.Receive(ack); } //Now we are done Finished(); } catch (Exception ex) { Debug.WriteLineIf(Rfc2812Util.IrcTrace.TraceWarning, "[" + Thread.CurrentThread.Name + "] DccFileSession::UploadLegacy() exception=" + ex); Interrupted(); } }
private void Listen() { Debug.WriteLineIf(DccUtil.DccTrace.TraceInfo, "[" + Thread.CurrentThread.Name + "] DccFileSession::Listen()"); try { //Wait for remote client to connect IPEndPoint localEndPoint = new IPEndPoint(DccUtil.LocalHost(), listenPort); serverSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); serverSocket.Bind(localEndPoint); serverSocket.Listen(1); //Got one! socket = serverSocket.Accept(); serverSocket.Close(); Debug.WriteLineIf(DccUtil.DccTrace.TraceInfo, "[" + Thread.CurrentThread.Name + "] DccFileSession::Listen() Remote user connected."); //Advance to the correct point in the file in case this is a resume dccFileInfo.GotoReadPosition(); SignalTransferStart(); if (turboMode) { Upload(); } else { UploadLegacy(); } } catch (Exception) { Debug.WriteLineIf(Rfc2812Util.IrcTrace.TraceWarning, "[" + Thread.CurrentThread.Name + "] DccFileSession::Listen() Connection broken"); Interrupted(); } }
private void Listen() { Debug.WriteLineIf(DccUtil.DccTrace.TraceInfo, "[" + Thread.CurrentThread.Name + "] DccChatSession::Listen()"); try { //Wait for remote client to connect IPEndPoint localEndPoint = new IPEndPoint(DccUtil.LocalHost(), listenPort); server = new TcpListener(localEndPoint); listening = true; server.Start(); //Got one! client = server.AcceptTcpClient(); server.Stop(); listening = false; Debug.WriteLineIf(DccUtil.DccTrace.TraceInfo, "[" + Thread.CurrentThread.Name + "] DccChatSession::Listen() Remote user connected."); if (OnChatSessionOpened != null) { OnChatSessionOpened(this); } //Start listening for messages ReceiveMessages(); } catch (Exception) { Debug.WriteLineIf(DccUtil.DccTrace.TraceInfo, "[" + Thread.CurrentThread.Name + "] DccChatSession::Listen() Connection broken"); } finally { SendClosedEvent(); } }
/// <summary> /// Create the correctly formatted DCC CHAT message and send it. /// </summary> private void SendChatRequest(string listenIPAddress, int listenPort) { //512 is the max IRC message size StringBuilder builder = new StringBuilder("PRIVMSG ", 512); builder.Append(dccUser.Nick); builder.Append(" :\x0001DCC CHAT CHAT "); builder.Append(DccUtil.IPAddressToLong(IPAddress.Parse(listenIPAddress)).ToString()); builder.Append(" "); builder.Append(listenPort); builder.Append("\x0001\n"); dccUser.Connection.Sender.Raw(builder.ToString()); }
private void DccSend(IPAddress sendAddress) { StringBuilder builder = new StringBuilder("PRIVMSG ", 512); builder.Append(dccUser.Nick); builder.Append(" :\x0001DCC SEND "); builder.Append(dccFileInfo.DccFileName); builder.Append(" "); builder.Append(DccUtil.IPAddressToLong(sendAddress).ToString()); builder.Append(" "); builder.Append(listenPort); builder.Append(" "); builder.Append(dccFileInfo.CompleteFileSize); builder.Append(turboMode ? " T" : ""); builder.Append("\x0001\n"); dccUser.Connection.Sender.Raw(builder.ToString()); }
private void Download() { Debug.WriteLineIf(DccUtil.DccTrace.TraceInfo, "[" + Thread.CurrentThread.Name + "] DccFileSession::Download()" + (turboMode ? " Turbo" : " Legacy") + " mode"); try { socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); socket.Connect(dccUser.RemoteEndPoint); int bytesRead = 0; while (!dccFileInfo.AllBytesTransfered()) { bytesRead = socket.Receive(buffer); //Remote server closed the connection before all bytes were sent if (bytesRead == 0) { Interrupted(); return; } ResetActivityTimer(); AddBytesProcessed(bytesRead); dccFileInfo.TransferStream.Write(buffer, 0, bytesRead); //Send ack if in legacy mode if (!turboMode) { socket.Send(DccUtil.DccBytesReceivedFormat(dccFileInfo.CurrentFilePosition())); } } dccFileInfo.TransferStream.Flush(); Finished(); } catch (Exception ex) { Debug.WriteLineIf(Rfc2812Util.IrcTrace.TraceWarning, "[" + Thread.CurrentThread.Name + "] DccFileSession::Download() exception=" + ex); if (ex.Message.IndexOf("refused") > 0) { dccUser.Connection.Listener.Error(ReplyCode.DccConnectionRefused, "Connection refused by remote user."); } else { dccUser.Connection.Listener.Error(ReplyCode.ConnectionFailed, "Unknown socket error:" + ex.Message); } Interrupted(); } }
internal void Parse(Connection connection, string message) { Debug.WriteLineIf(DccUtil.DccTrace.TraceInfo, "[" + Thread.CurrentThread.Name + "] DccListener::Parse()"); Match match = parser.Match(message); string requestor = match.Groups[1].ToString(); string[] tokens = tokenizer.Split(match.Groups[2].ToString().Trim()); switch (tokens[Action]) { case CHAT: if (OnDccChatRequest != null) { //Test for sufficient number of arguments if (tokens.Length < 4) { connection.Listener.Error(ReplyCode.UnparseableMessage, "Incorrect CHAT arguments: " + message); return; } //Send event DccUser dccUser = null; try { dccUser = new DccUser( connection, Rfc2812Util.ParseUserLine(requestor), new IPEndPoint(DccUtil.LongToIPAddress(tokens[Address]), int.Parse(tokens[Port], CultureInfo.InvariantCulture))); } catch (ArgumentException) { connection.Listener.Error(ReplyCode.BadDccEndpoint, "Invalid TCP/IP connection information sent."); return; } try { OnDccChatRequest(dccUser); } catch (ArgumentException ae) { connection.Listener.Error(ReplyCode.UnknownEncryptionProtocol, ae.ToString()); } } break; case SEND: //Test for sufficient number of arguments if (tokens.Length < 5) { connection.Listener.Error(ReplyCode.UnparseableMessage, "Incorrect SEND arguments: " + message); return; } if (OnDccSendRequest != null) { DccUser dccUser = null; try { dccUser = new DccUser( connection, Rfc2812Util.ParseUserLine(requestor), new IPEndPoint(DccUtil.LongToIPAddress(tokens[Address]), int.Parse(tokens[Port], CultureInfo.InvariantCulture))); } catch (ArgumentException ae) { connection.Listener.Error(ReplyCode.BadDccEndpoint, ae.ToString()); return; } try { OnDccSendRequest( dccUser, tokens[FileName], int.Parse(tokens[FileSize], CultureInfo.InvariantCulture), IsTurbo(5, tokens)); } catch (ArgumentException ae) { connection.Listener.Error(ReplyCode.UnknownEncryptionProtocol, ae.ToString()); } } break; case GET: //Test for sufficient number of arguments if (tokens.Length < 2) { connection.Listener.Error(ReplyCode.UnparseableMessage, "Incorrect GET arguments: " + message); return; } if (OnDccGetRequest != null) { try { OnDccGetRequest( new DccUser( connection, Rfc2812Util.ParseUserLine(requestor)), tokens[FileName], IsTurbo(2, tokens)); } catch (ArgumentException ae) { connection.Listener.Error(ReplyCode.UnknownEncryptionProtocol, ae.ToString()); } } break; case ACCEPT: //Test for sufficient number of arguments if (tokens.Length < 4) { connection.Listener.Error(ReplyCode.UnparseableMessage, "Incorrect DCC ACCEPT arguments: " + message); return; } //DccListener will try to handle Receive at correct file position try { DccFileSession session = DccFileSessionManager.DefaultInstance.LookupSession("C" + tokens[2]); session.OnDccAcceptReceived(long.Parse(tokens[3], CultureInfo.InvariantCulture)); } catch (ArgumentException e) { connection.Listener.Error(ReplyCode.UnableToResume, e.ToString()); } break; case RESUME: //Test for sufficient number of arguments if (tokens.Length < 4) { connection.Listener.Error(ReplyCode.UnparseableMessage, "Incorrect DCC RESUME arguments: " + message); return; } //DccListener will automatically handle Resume/Accept interaction try { DccFileSession session = DccFileSessionManager.DefaultInstance.LookupSession("S" + tokens[2]); session.OnDccResumeRequest(long.Parse(tokens[3], CultureInfo.InvariantCulture)); } catch (ArgumentException e) { connection.Listener.Error(ReplyCode.UnableToResume, e.ToString()); } break; default: connection.Listener.Error(ReplyCode.UnparseableMessage, message); Debug.WriteLineIf(DccUtil.DccTrace.TraceError, "[" + Thread.CurrentThread.Name + "] DccListener::Parse() Unknown DCC command"); break; } }