public override bool ProcessPDU(LLCP_Link link, LLCP_PDU recv_pdu) { /* Server action */ /* ------------- */ link.RemotePort = recv_pdu.SSAP; link.LocalPort = (byte)(_server_port & 0x3F); switch (recv_pdu.PTYPE) { case LLCP_PDU.PTYPE_CONNECT: Trace.WriteLine("> CONNECT"); /* The client wants to connect us */ link.State = LLCP_Link.StateActive; if (!OnConnect(link, recv_pdu.Payload)) { /* Failed */ link.Send_DM(LLCP_DM_PDU.REASON_REJECTED); /* 03 */ /* Drop the link */ return(false); } else if (!link.Answered) { /* Confirm we agree (CC) */ link.Send_CC(); } break; case LLCP_PDU.PTYPE_DISC: Trace.WriteLine("> DISC"); /* The client is leaving us */ if (link.State == LLCP_Link.StateActive) { OnDisconnect(link); link.Send_DM(LLCP_DM_PDU.REASON_DISC_OK); /* 00 */ } else { link.Send_DM(LLCP_DM_PDU.REASON_NO_CONNECTION); /* 01 */ } /* Drop the link */ return(false); case LLCP_PDU.PTYPE_I: Trace.WriteLine("> I"); /* The client is talking to us */ if (link.State == LLCP_Link.StateActive) { byte nr = (byte)(recv_pdu.Sequence & 0x0F); byte ns = (byte)((recv_pdu.Sequence >> 4) & 0x0F); link.SetRemoteSequence((byte)((ns + 1) & 0x0F)); OnInformation(link, recv_pdu.Payload); if (!link.Answered) { /* No frame -> ACK */ link.Send_RR(); } } else { link.Send_DM(LLCP_DM_PDU.REASON_NO_CONNECTION); /* 01 */ } break; case LLCP_PDU.PTYPE_RR: Trace.WriteLine("> RR"); /* The client is acknowledging */ if (link.State == LLCP_Link.StateActive) { byte nr = (byte)(recv_pdu.Sequence & 0x0F); OnAcknowledge(link); } else { link.Send_DM(LLCP_DM_PDU.REASON_NO_CONNECTION); /* 01 */ } break; default: Trace.WriteLine("Unsupported LLCP frame client->server"); link.Send_FRMR(0x80, recv_pdu.PTYPE, 0x00); /* Drop the link */ return(false); } /* Keep the link OK */ return(true); }
protected bool HandleRecvPDU(LLCP_PDU recv_pdu) { LLCP_Link link; if ((recv_pdu.DSAP == 0) && (recv_pdu.SSAP == 0)) { /* Management PDUs */ /* --------------- */ return(HandleManagementPDU(recv_pdu)); } SymmCount = 0; if (recv_pdu.PTYPE == LLCP_PDU.PTYPE_CONNECT) { /* Handle CONNECT */ /* -------------- */ Trace.WriteLine("> CONNECT"); /* Name server is listening on address 01 */ if (recv_pdu.DSAP == ADDR_NAME_SERVER) { /* Using name server */ string server_name = FindParameterStr(recv_pdu.Payload, LLCP.PARAM_SERVICE_NAME); if (server_name != null) { Trace.WriteLine("Looking for server '" + server_name + "'"); /* Looking for a server by its name */ for (int i = 0; i < _servers.Count; i++) { if (_servers[i].ServerName == server_name) { link = new LLCP_Link(this, _servers[i], recv_pdu); link.LocalPort = _servers[i].ServerPort; if (link.ProcessPDU(recv_pdu)) { _links.Add(link); } return(true); } } } } else { /* Using server address */ Trace.WriteLine("Looking for server " + recv_pdu.DSAP); for (int i = 0; i < _servers.Count; i++) { if (_servers[i].ServerPort == recv_pdu.DSAP) { link = new LLCP_Link(this, _servers[i], recv_pdu); if (link.ProcessPDU(recv_pdu)) { _links.Add(link); } return(true); } } } } /* Looking for an already-connected Server, or already instancied Client */ /* --------------------------------------------------------------------- */ for (int i = 0; i < _links.Count; i++) { if (_links[i].LocalPort == recv_pdu.DSAP) { if (!_links[i].ProcessPDU(recv_pdu)) { /* Drop the link */ _links.RemoveAt(i); } return(true); } } /* No client, no server, and DSAP or SSAP != 0 */ link = new LLCP_Link(this, null, recv_pdu); switch (recv_pdu.PTYPE) { case LLCP_PDU.PTYPE_CONNECT: /* Peer is trying to connect to a non-existing service */ Trace.WriteLine("CONNECT to non existing server"); link.Send_DM(LLCP_DM_PDU.REASON_NO_SERVICE); break; case LLCP_PDU.PTYPE_RR: case LLCP_PDU.PTYPE_I: Trace.WriteLine("I or RR to non active service"); link.Send_DM(LLCP_DM_PDU.REASON_NO_CONNECTION); /* 01 */ break; default: Trace.WriteLine("No client, no server, bad PTYPE"); break; } return(true); }