mirror of
https://github.com/haiwen/ccnet-server.git
synced 2025-05-02 04:23:20 +00:00
149 lines
4.6 KiB
Python
149 lines
4.6 KiB
Python
#coding: UTF-8
|
|
|
|
import os
|
|
import socket
|
|
import ConfigParser
|
|
import logging
|
|
|
|
from ccnet.packet import to_request_id, to_update_id
|
|
from ccnet.packet import request_to_packet, update_to_packet
|
|
from ccnet.packet import write_packet
|
|
|
|
from ccnet.errors import NetworkError
|
|
|
|
from .utils import is_win32, make_socket_closeonexec
|
|
|
|
CCNET_PIPE_NAME = 'ccnet.sock'
|
|
|
|
def parse_response(body):
|
|
'''Parse the content of the response
|
|
The struct of response data:
|
|
- first 3 bytes is the <status code>
|
|
- from the 4th byte to the first occurrence of '\n' is the <status message>. If the 4th byte is '\n', then there is no <status message>
|
|
- from the first occurrence of '\n' to the end is the <content>
|
|
'''
|
|
code = body[:3]
|
|
if body[3] == '\n':
|
|
code_msg = ''
|
|
content = body[4:]
|
|
else:
|
|
pos = body.index('\n')
|
|
code_msg = body[4:pos]
|
|
content = body[pos + 1:]
|
|
|
|
return code, code_msg, content
|
|
|
|
def parse_update(body):
|
|
'''The structure of an update is the same with a response'''
|
|
code = body[:3]
|
|
if body[3] == '\n':
|
|
code_msg = ''
|
|
content = body[4:]
|
|
else:
|
|
pos = body.index('\n')
|
|
code_msg = body[4:pos]
|
|
content = body[pos + 1:]
|
|
|
|
return code, code_msg, content
|
|
|
|
class Client(object):
|
|
'''Base ccnet client class'''
|
|
def __init__(self, config_dir, central_config_dir=None):
|
|
if not isinstance(config_dir, unicode):
|
|
config_dir = config_dir.decode('UTF-8')
|
|
|
|
if central_config_dir:
|
|
central_config_dir = os.path.expanduser(central_config_dir)
|
|
if not os.path.exists(central_config_dir):
|
|
raise RuntimeError(u'%s does not exits' % central_config_dir)
|
|
config_dir = os.path.expanduser(config_dir)
|
|
config_file = os.path.join(central_config_dir if central_config_dir else config_dir,
|
|
u'ccnet.conf')
|
|
logging.debug('using config file %s', config_file)
|
|
if not os.path.exists(config_file):
|
|
raise RuntimeError(u'%s does not exits' % config_file)
|
|
|
|
self.central_config_dir = central_config_dir
|
|
self.config_dir = config_dir
|
|
self.config_file = config_file
|
|
self.config = None
|
|
|
|
self.port = None
|
|
self.peer_id = None
|
|
self.peer_name = None
|
|
|
|
self.parse_config()
|
|
|
|
self._connfd = None
|
|
self._req_id = 1000
|
|
|
|
def __del__(self):
|
|
'''Destructor of the client class. We close the socket here, if
|
|
connetced to daemon
|
|
|
|
'''
|
|
if self.is_connected():
|
|
try:
|
|
self._connfd.close()
|
|
except:
|
|
pass
|
|
|
|
def parse_config(self):
|
|
self.config = ConfigParser.ConfigParser()
|
|
self.config.read(self.config_file)
|
|
if self.config.has_option('Client', 'PORT'):
|
|
self.port = self.config.getint('Client', 'PORT')
|
|
else:
|
|
self.port = 10001
|
|
self.un_path = ''
|
|
if self.config.has_option('Client', 'UNIX_SOCKET'):
|
|
self.un_path = self.config.get('Client', 'UNIX_SOCKET')
|
|
self.peer_id = self.config.get('General', 'ID')
|
|
self.peer_name = self.config.get('General', 'NAME')
|
|
|
|
def connect_daemon_with_pipe(self):
|
|
self._connfd = socket.socket(socket.AF_UNIX)
|
|
if not self.un_path:
|
|
pipe_name = os.path.join(self.config_dir, CCNET_PIPE_NAME)
|
|
else:
|
|
pipe_name = self.un_path
|
|
try:
|
|
self._connfd.connect(pipe_name)
|
|
except:
|
|
raise NetworkError("Can't connect to daemon")
|
|
|
|
make_socket_closeonexec(self._connfd.fileno())
|
|
|
|
def connect_daemon_with_socket(self):
|
|
self._connfd = socket.socket()
|
|
self._connfd.setsockopt(socket.SOL_TCP, socket.TCP_NODELAY, 1)
|
|
try:
|
|
self._connfd.connect(('127.0.0.1', self.port))
|
|
except:
|
|
raise NetworkError("Can't connect to daemon")
|
|
|
|
make_socket_closeonexec(self._connfd.fileno())
|
|
|
|
def connect_daemon(self):
|
|
if is_win32():
|
|
return self.connect_daemon_with_socket()
|
|
else:
|
|
return self.connect_daemon_with_pipe()
|
|
|
|
def is_connected(self):
|
|
return self._connfd is not None
|
|
|
|
def send_request(self, id, req):
|
|
id = to_request_id(id)
|
|
pkt = request_to_packet(id, req)
|
|
write_packet(self._connfd, pkt)
|
|
|
|
def send_update(self, id, code, code_msg, content=''):
|
|
id = to_update_id(id)
|
|
pkt = update_to_packet(id, code, code_msg, content)
|
|
write_packet(self._connfd, pkt)
|
|
|
|
def get_request_id(self):
|
|
self._req_id += 1
|
|
return self._req_id
|