internal ObexListenerContext(SocketAdapter s) { buffer = new byte[0x2000]; this.localEndPoint = s.LocalEndPoint; this.remoteEndPoint = s.RemoteEndPoint; bool moretoreceive = true; bool putCompleted = false; while (moretoreceive) { //receive the request and store the data for the request object int received = 0; try { while (received < 3) { int readLen = s.Receive(buffer, received, 3 - received, SocketFlags.None); if (readLen == 0) { moretoreceive = false; if (received == 0) { break; // Waiting for first byte of packet -- OK to close then. } else { throw new EndOfStreamException("Connection lost."); } } received += readLen; } //Debug.WriteLine(s.GetHashCode().ToString("X8") + ": RecvH", "ObexListener"); } catch (SocketException se) { //Console.Write(se.Message); HandleConnectionError(se); } if (received == 3) { ObexMethod method = (ObexMethod)buffer[0]; //get length (excluding the 3 byte header) short len = (short)(IPAddress.NetworkToHostOrder(BitConverter.ToInt16(buffer, 1)) - 3); if (len > 0) { int iPos = 0; while (iPos < len) { int wanted = len - iPos; Debug.Assert(wanted > 0, "NOT wanted > 0, is: " + wanted); int receivedBytes = s.Receive(this.buffer, iPos + 3, wanted, SocketFlags.None); if (receivedBytes == 0) { moretoreceive = false; throw new EndOfStreamException("Connection lost."); } iPos += receivedBytes; } } byte[] responsePacket; // Don't init, then the compiler will check that it's set below. //Debug.WriteLine(s.GetHashCode().ToString("X8") + ": Method: " + method, "ObexListener"); responsePacket = HandleAndMakeResponse(ref moretoreceive, ref putCompleted, method); try { System.Diagnostics.Debug.Assert(responsePacket != null, "Must always respond to the peer."); if (responsePacket != null) { s.Send(responsePacket); } } catch (Exception se) { //Console.WriteLine(se.Message); HandleConnectionError(se); } } else { moretoreceive = false; } }//while Debug.WriteLine(s.GetHashCode().ToString("X8") + ": Completed", "ObexListener"); s.Close(); s = null; if (!putCompleted) { // Should not return the request. throw new ProtocolViolationException("No PutFinal received."); } request = new ObexListenerRequest(bodyStream.ToArray(), headers, localEndPoint, remoteEndPoint); }
internal static void ParseHeaders(byte[] packet, bool isConnectPacket, ref ushort remoteMaxPacket, Stream bodyStream, WebHeaderCollection headers) { ObexMethod method = (ObexMethod)packet[0]; int packetLength = IPAddress.NetworkToHostOrder(BitConverter.ToInt16(packet, 1)); int pos = 3; int lastPos = int.MinValue; while (pos < packetLength) { if (pos == lastPos) { Debug.Fail("Infinite Loop!"); throw new InvalidOperationException("Infinite Loop!"); } lastPos = pos; ObexHeader header = (ObexHeader)packet[pos]; switch (header) { case ObexHeader.None: return; case (ObexHeader)0x10: Debug.Assert(isConnectPacket, "NOT isConnectPacket"); Debug.Assert(pos == 3, "NOT before any headers!"); remoteMaxPacket = unchecked ((ushort)IPAddress.NetworkToHostOrder(BitConverter.ToInt16(packet, pos + 2))); pos += 4; break; case ObexHeader.ConnectionID: case ObexHeader.Count: case ObexHeader.Length: case ObexHeader.CreatorID: case ObexHeader.Time4Byte: int intValue = IPAddress.NetworkToHostOrder(BitConverter.ToInt32(packet, pos + 1)); pos += 5; string key = header.ToString().ToUpper(); string value = intValue.ToString(); // Duplicate headers causes comma-separated HTTP list!! if (-1 != Array.IndexOf <string>(headers.AllKeys, key)) { string existing = headers.Get(key); if (value == existing) { // Just discard it then. break; } else { Debug.Assert(-1 == Array.IndexOf <string>(headers.AllKeys, header.ToString().ToUpper()), "Duplicate headers causes comma-separated HTTP list!!: " + header.ToString().ToUpper()); } } headers.Add(header.ToString().ToUpper(), intValue.ToString()); break; case ObexHeader.Who: short whoSize = IPAddress.NetworkToHostOrder(BitConverter.ToInt16(packet, pos + 1)); byte[] whoBytes = new byte[16]; Buffer.BlockCopy(packet, pos + 3, whoBytes, 0, whoSize - 3); Guid service = new Guid(whoBytes); headers.Add(header.ToString().ToUpper(), service.ToString()); pos += whoSize; break; case ObexHeader.Body: case ObexHeader.EndOfBody: short bodySize = IPAddress.NetworkToHostOrder(BitConverter.ToInt16(packet, pos + 1)); bodyStream.Write(packet, pos + 3, bodySize - 3); pos += bodySize; break; case ObexHeader.Type: int typeSize = IPAddress.NetworkToHostOrder(BitConverter.ToInt16(packet, pos + 1)); if (typeSize > 3) { string typeString = System.Text.Encoding.ASCII.GetString(packet, pos + 3, typeSize - 4); if (typeString != null) { int nullindex = typeString.IndexOf('\0'); if (nullindex > -1) { typeString = typeString.Substring(0, nullindex); } if (typeString != string.Empty) { headers.Add(header.ToString().ToUpper(), typeString); } } } pos += typeSize; break; default: int headerSize = IPAddress.NetworkToHostOrder(BitConverter.ToInt16(packet, pos + 1)); if (headerSize > 3) { string headerString = System.Text.Encoding.BigEndianUnicode.GetString(packet, pos + 3, headerSize - 5); if (headerString != null) { int nullindex = headerString.IndexOf('\0'); if (nullindex > -1) { headerString = headerString.Substring(0, nullindex); } if (headerString != string.Empty) { headers.Add(header.ToString().ToUpper(), Uri.EscapeDataString(headerString)); } } } pos += headerSize; break; } } }
private byte[] HandleAndMakeResponse(ref bool moretoreceive, ref bool putCompleted, ObexMethod method) { byte[] responsePacket; switch (method) { case ObexMethod.Connect: ObexParser.ParseHeaders(buffer, true, ref remoteMaxPacket, bodyStream, headers); responsePacket = new byte[7] { 0xA0, 0x00, 0x07, 0x10, 0x00, 0x20, 0x00 }; break; case ObexMethod.Put: if (putCompleted) // Don't allow another PUT to append to the previous content! { goto case ObexMethod.PutFinal; } ObexParser.ParseHeaders(buffer, false, ref remoteMaxPacket, bodyStream, headers); responsePacket = new byte[3] { (byte)(ObexStatusCode.Continue | ObexStatusCode.Final), 0x00, 0x03 }; break; case ObexMethod.PutFinal: if (putCompleted) // Don't allow another PUT to append to the previous content! { ObexStatusCode code = ObexStatusCode.Forbidden; // Any better one? responsePacket = new byte[3] { (byte)(code | ObexStatusCode.Final), 0x00, 0x03 }; moretoreceive = false; break; } ObexParser.ParseHeaders(buffer, false, ref remoteMaxPacket, bodyStream, headers); responsePacket = new byte[3] { (byte)(ObexStatusCode.OK | ObexStatusCode.Final), 0x00, 0x03 }; // Shouldn't return an object if the sender didn't send it all. putCompleted = true; // (Need to just assume that it does contains EndOfBody) break; case ObexMethod.Disconnect: ObexParser.ParseHeaders(buffer, false, ref remoteMaxPacket, bodyStream, headers); responsePacket = new byte[3] { (byte)(ObexStatusCode.OK | ObexStatusCode.Final), 0x00, 0x03 }; moretoreceive = false; break; default: //Console.WriteLine(method.ToString() + " " + received.ToString()); responsePacket = new byte[3] { (byte)ObexStatusCode.NotImplemented, 0x00, 0x03 }; break; } return(responsePacket); }