summaryrefslogtreecommitdiff
path: root/src/PeerMessageUtil.cc
blob: b13cb40127bf85a68b5a3da5b8e7873dd8e62174 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
/* <!-- copyright */
/*
 * aria2 - a simple utility for downloading files faster
 *
 * Copyright (C) 2006 Tatsuhiro Tsujikawa
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 */
/* copyright --> */
#include "PeerMessageUtil.h"
#include "DlAbortEx.h"
#include "Util.h"
#include <netinet/in.h>

int PeerMessageUtil::getId(const char* msg) {
  return (int)msg[0];
}

int PeerMessageUtil::getIntParam(const char* msg, int offset) {
  int nParam;
  memcpy(&nParam, msg+offset, 4);
  return ntohl(nParam);
}

int PeerMessageUtil::getShortIntParam(const char* msg, int offset) {
  short int nParam;
  memcpy(&nParam, msg+offset, 2);
  return ntohs(nParam);
}

void PeerMessageUtil::checkIndex(int index, int pieces) {
  if(!(0 <= index && index < pieces)) {
    throw new DlAbortEx("invalid index = %d", index);
  }
}

void PeerMessageUtil::checkBegin(int begin, int pieceLength) {
  if(!(0 <= begin && begin < pieceLength)) {
    throw new DlAbortEx("invalid begin = %d", begin);
  }  
}

void PeerMessageUtil::checkLength(int length) {
  if(length > MAX_BLOCK_LENGTH) {
    throw new DlAbortEx("too large length %d > %dKB", length,
			MAX_BLOCK_LENGTH/1024);
  }
  if(length <= 0) {
    throw new DlAbortEx("invalid length %d", length);
  }
  if(!Util::isPowerOf(length, 2)) {
    throw new DlAbortEx("invalid length %d, which is not power of 2",
			length);
  }
}

void PeerMessageUtil::checkRange(int begin, int length, int pieceLength) {
  if(!(0 <= begin && 0 < length)) {
    throw new DlAbortEx("invalid range, begin = %d, length = %d",
			begin, length);
  }
  int end = begin+length;
  if(!(0 < end && end <= pieceLength)) {
    throw new DlAbortEx("invalid range, begin = %d, length = %d",
			begin, length);
  }
}

void PeerMessageUtil::checkBitfield(const unsigned char* bitfield, int bitfieldLength, int pieces) {
  if(!(bitfieldLength == BITFIELD_LEN_FROM_PIECES(pieces))) {
    throw new DlAbortEx("invalid bitfield length = %d",
			bitfieldLength);
  }
  char lastbyte = bitfield[bitfieldLength-1];
  for(int i = 0; i < 8-pieces%8 && pieces%8 != 0; i++) {
    if(!(((lastbyte >> i) & 1) == 0)) {
      throw new DlAbortEx("invalid bitfield");
    }
  }
}

void PeerMessageUtil::checkHandshake(const HandshakeMessage* message, const unsigned char* infoHash) {
  if(message->pstrlen != 19) {
    throw new DlAbortEx("invalid handshake pstrlen = %d", (int)message->pstrlen);
  }
  if(message->pstr != PSTR) {
    throw new DlAbortEx("invalid handshake pstr");
  }
  string myInfoHash = Util::toHex(infoHash, 20);
  string peerInfoHash = Util::toHex(message->infoHash, 20);
  if(myInfoHash != peerInfoHash) {
    throw new DlAbortEx("invalid handshake info hash: expected:%s, actual:%s",
			myInfoHash.c_str(), peerInfoHash.c_str());
  }
}

void PeerMessageUtil::setIntParam(char* dest, int param) {
  int nParam = htonl(param);
  memcpy(dest, &nParam, 4);
}

void PeerMessageUtil::createPeerMessageString(char* msg, int msgLength,
					      int payloadLength,
					      int messageId) {
  assert(msgLength >= 5);
  memset(msg, 0, msgLength);
  setIntParam(msg, payloadLength);
  msg[4] = (char)messageId;
}