mirror of
https://github.com/haiwen/ccnet-server.git
synced 2025-09-08 16:18:58 +00:00
Initial commit of Ccnet server.
This commit is contained in:
129
python/ccnet/packet.py
Normal file
129
python/ccnet/packet.py
Normal file
@@ -0,0 +1,129 @@
|
||||
#coding: UTF-8
|
||||
|
||||
"""
|
||||
Packet level protocol of ccnet.
|
||||
|
||||
About various types of id:
|
||||
|
||||
- A slave processor's id has its highest bit set; a master processor has its highest bit clear
|
||||
- The <id> field of a ccnet packet always has its highest bit clear. The
|
||||
<type> field of the packet determines what type of the packet is (a
|
||||
request, a response, or an update)
|
||||
"""
|
||||
|
||||
import logging
|
||||
import struct
|
||||
|
||||
from ccnet.utils import recvall, sendall, NetworkError
|
||||
|
||||
REQUEST_ID_MASK = 0x7fffffff
|
||||
SLAVE_BIT_MASK = 0x80000000
|
||||
|
||||
CCNET_MSG_OK = 0
|
||||
CCNET_MSG_HANDSHAKE = 1
|
||||
CCNET_MSG_REQUEST = 2
|
||||
CCNET_MSG_RESPONSE = 3
|
||||
CCNET_MSG_UPDATE = 4
|
||||
CCNET_MSG_RELAY = 5
|
||||
|
||||
def to_request_id(id):
|
||||
return id & REQUEST_ID_MASK
|
||||
|
||||
to_response_id = to_request_id
|
||||
to_update_id = to_request_id
|
||||
to_master_id = to_request_id
|
||||
to_packet_id = to_request_id
|
||||
|
||||
def to_slave_id(id):
|
||||
return id | SLAVE_BIT_MASK
|
||||
|
||||
def to_print_id(id):
|
||||
if id & SLAVE_BIT_MASK:
|
||||
return -to_request_id(id)
|
||||
else:
|
||||
return id
|
||||
|
||||
# the byte sequence of ccnet packet header
|
||||
CCNET_HEADER_FORMAT = '>BBHI'
|
||||
# Number of bytes for the header
|
||||
CCNET_HEADER_LENGTH = struct.calcsize(CCNET_HEADER_FORMAT)
|
||||
|
||||
CCNET_MAX_PACKET_LENGTH = 65535
|
||||
|
||||
class PacketHeader(object):
|
||||
def __init__(self, ver, ptype, length, id):
|
||||
self.ver = ver
|
||||
self.ptype = ptype
|
||||
self.length = length
|
||||
self.id = id
|
||||
|
||||
def to_string(self):
|
||||
return struct.pack(CCNET_HEADER_FORMAT, self.ver, self.ptype, self.length, self.id)
|
||||
|
||||
def __str__(self):
|
||||
return "<PacketHeader: type = %d, length = %d, id = %u>" % (self.ptype, self.length, self.id)
|
||||
|
||||
class Packet(object):
|
||||
version = 1
|
||||
def __init__(self, header, body):
|
||||
self.header = header
|
||||
self.body = body
|
||||
|
||||
def parse_header(buf):
|
||||
try:
|
||||
ver, ptype, length, id = struct.unpack(CCNET_HEADER_FORMAT, buf)
|
||||
except struct.error, e:
|
||||
raise NetworkError('error when unpack packet header: %s' % e)
|
||||
|
||||
return PacketHeader(ver, ptype, length, id)
|
||||
|
||||
def format_response(code, code_msg, content):
|
||||
body = code
|
||||
if code_msg:
|
||||
body += " " + code_msg
|
||||
body += "\n"
|
||||
|
||||
if content:
|
||||
body += content
|
||||
|
||||
return body
|
||||
|
||||
format_update = format_response
|
||||
|
||||
def request_to_packet(id, buf):
|
||||
hdr = PacketHeader(1, CCNET_MSG_REQUEST, len(buf), to_request_id(id))
|
||||
return Packet(hdr, buf)
|
||||
|
||||
def response_to_packet(id, code, code_msg, content):
|
||||
body = format_response(code, code_msg, content)
|
||||
hdr = PacketHeader(1, CCNET_MSG_RESPONSE, len(body), to_response_id(id))
|
||||
return Packet(hdr, body)
|
||||
|
||||
def update_to_packet(id, code, code_msg, content):
|
||||
body = format_update(code, code_msg, content)
|
||||
hdr = PacketHeader(1, CCNET_MSG_UPDATE, len(body), to_update_id(id))
|
||||
return Packet(hdr, body)
|
||||
|
||||
def read_packet(fd):
|
||||
hdr = recvall(fd, CCNET_HEADER_LENGTH)
|
||||
if len(hdr) == 0:
|
||||
logging.warning('connection to daemon is lost')
|
||||
raise NetworkError('Connection to daemon is lost')
|
||||
elif len(hdr) < CCNET_HEADER_LENGTH:
|
||||
raise NetworkError('Only read %d bytes header, expected 8' % len(hdr))
|
||||
|
||||
header = parse_header(hdr)
|
||||
|
||||
if header.length == 0:
|
||||
body = ''
|
||||
else:
|
||||
body = recvall(fd, header.length)
|
||||
if len(body) < header.length:
|
||||
raise NetworkError('Only read %d bytes body, expected %d' % (len(body), header.length))
|
||||
|
||||
return Packet(header, body)
|
||||
|
||||
def write_packet(fd, packet):
|
||||
hdr = packet.header.to_string()
|
||||
sendall(fd, hdr)
|
||||
sendall(fd, packet.body)
|
Reference in New Issue
Block a user