// Decode a job from byte slice func decodeJob(data []byte) (job *Job, err error) { if len(data) < 12 { return nil, common.Errorf("Invalid data: %V", data) } datatype := common.BytesToUint32([4]byte{data[4], data[5], data[6], data[7]}) l := common.BytesToUint32([4]byte{data[8], data[9], data[10], data[11]}) if len(data[12:]) != int(l) { return nil, common.Errorf("Invalid data: %V", data) } data = data[12:] var handle string switch datatype { case common.WORK_DATA, common.WORK_WARNING, common.WORK_STATUS, common.WORK_COMPLETE, common.WORK_FAIL, common.WORK_EXCEPTION: i := bytes.IndexByte(data, '\x00') if i != -1 { handle = string(data[:i]) data = data[i+1:] } } return &Job{magicCode: common.RES, DataType: datatype, Data: data, Handle: handle}, nil }
// Decode job from byte slice func decodeJob(data []byte) (job *Job, err error) { if len(data) < 12 { return nil, common.Errorf("Invalid data: %V", data) } datatype := common.BytesToUint32([4]byte{data[4], data[5], data[6], data[7]}) l := common.BytesToUint32([4]byte{data[8], data[9], data[10], data[11]}) if len(data[12:]) != int(l) { return nil, common.Errorf("Invalid data: %V", data) } data = data[12:] job = &Job{magicCode: common.RES, DataType: datatype, c: make(chan bool)} switch datatype { case common.JOB_ASSIGN: s := bytes.SplitN(data, []byte{'\x00'}, 3) if len(s) == 3 { job.Handle = string(s[0]) job.Fn = string(s[1]) data = s[2] } case common.JOB_ASSIGN_UNIQ: s := bytes.SplitN(data, []byte{'\x00'}, 4) if len(s) == 4 { job.Handle = string(s[0]) job.Fn = string(s[1]) job.UniqueId = string(s[2]) data = s[3] } } job.Data = data return }
// Decode a job from byte slice func decodeJob(data []byte) (job *Job, err error) { if len(data) < 12 { return nil, common.Errorf("Invalid data: %V", data) } datatype := common.BytesToUint32([4]byte{data[4], data[5], data[6], data[7]}) l := common.BytesToUint32([4]byte{data[8], data[9], data[10], data[11]}) if len(data[12:]) != int(l) { return nil, common.Errorf("Invalid data: %V", data) } data = data[12:] return newJob(common.RES, datatype, data), nil }
// unpack data func (client *Client) unpack(data []byte) ([]byte, int, bool) { tl := len(data) start := 0 for i := 0; i < tl+1-common.PACKET_LEN; i++ { if start+common.PACKET_LEN > tl { // too few data to unpack, read more return nil, common.PACKET_LEN, false } if string(data[start:start+4]) == common.RES_STR { l := int(common.BytesToUint32([4]byte{data[start+8], data[start+9], data[start+10], data[start+11]})) total := l + common.PACKET_LEN if total == tl { // data is what we want return data, common.PACKET_LEN, true } else if total < tl { // data[:total] is what we want, data[total:] is the more client.in <- data[total:] data = data[start:total] return data, common.PACKET_LEN, true } else { // ops! It won't be possible. return nil, total - tl, false } } else { // flag was not found, move to next step start++ } } return nil, common.PACKET_LEN, false }
// Internal read func (a *agent) read() (data []byte, err error) { BEGIN: inlen := len(a.in) if inlen > 0 { // in queue is not empty for i := 0; i < inlen; i++ { data = append(data, <-a.in...) } } else { for { buf := make([]byte, common.BUFFER_SIZE) var n int if n, err = a.conn.Read(buf); err != nil { if err == io.EOF && n == 0 { if data == nil { err = common.ErrConnection return } break } return } data = append(data, buf[0:n]...) if n < common.BUFFER_SIZE { break } } } // split package tl := len(data) if tl < 12 { // too few data to unpack, read more goto BEGIN } start := 0 for i := 0; i < tl-11; i++ { if start+12 > tl { // too few data to unpack, read more goto BEGIN } if string(data[start:start+4]) == common.RES_STR { l := int(common.BytesToUint32([4]byte{data[start+8], data[start+9], data[start+10], data[start+11]})) total := l + 12 if total == tl { // data is what we want return } else if total < tl { // data[:total] is what we want, data[total:] is the more a.in <- data[total:] data = data[:total] return } else { // ops! It won't be possible. goto BEGIN } } else { // flag was not found, move to next step start++ } } goto BEGIN return nil, common.Errorf("Invalid data: %V", data) }
// inner read func (client *Client) read() (data []byte, err error) { if len(client.in) > 0 { // incoming queue is not empty data = <-client.in } else { // empty queue, read data from socket for { buf := make([]byte, common.BUFFER_SIZE) var n int if n, err = client.conn.Read(buf); err != nil { if err == io.EOF && n == 0 { if data == nil { err = common.ErrConnection return } break } return } data = append(data, buf[0:n]...) if n < common.BUFFER_SIZE { break } } } // split package tl := len(data) start, end := 0, 4 for i := 0; i < tl; i++ { if string(data[start:end]) == common.RES_STR { l := int(common.BytesToUint32([4]byte{data[start+8], data[start+9], data[start+10], data[start+11]})) total := l + 12 if total == tl { return } else { client.in <- data[total:] data = data[:total] return } } else { start++ end++ } } return nil, common.Errorf("Invalid data: %V", data) }