1 /*
2 * Copyright (C) 2016 Jakub Kruszona-Zawadzki, Core Technology Sp. z o.o.
3 *
4 * This file is part of MooseFS.
5 *
6 * MooseFS is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation, version 2 (only).
9 *
10 * MooseFS is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with MooseFS; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02111-1301, USA
18 * or visit http://www.gnu.org/licenses/gpl-2.0.html
19 */
20
21 #ifdef HAVE_CONFIG_H
22 #include "config.h"
23 #endif
24
25 #include <stdio.h>
26 #include <stdlib.h>
27 #include <string.h>
28 #include <unistd.h>
29 #include <time.h>
30 #include <errno.h>
31 #include <syslog.h>
32
33 #include "MFSCommunication.h"
34 #include "sockets.h"
35 #include "datapack.h"
36 #include "strerr.h"
37 #include "mfsstrerr.h"
38 #include "crc.h"
39
40 #define CSMSECTIMEOUT 5000
41
cs_readblock(int fd,uint64_t chunkid,uint32_t version,uint32_t offset,uint32_t size,uint8_t * buff)42 int cs_readblock(int fd,uint64_t chunkid,uint32_t version,uint32_t offset,uint32_t size,uint8_t *buff) {
43 uint8_t *wptr,ibuff[28];
44 const uint8_t *rptr;
45
46 wptr = ibuff;
47 put32bit(&wptr,CLTOCS_READ);
48 put32bit(&wptr,20);
49 put64bit(&wptr,chunkid);
50 put32bit(&wptr,version);
51 put32bit(&wptr,offset);
52 put32bit(&wptr,size);
53 if (tcptowrite(fd,ibuff,28,CSMSECTIMEOUT)!=28) {
54 syslog(LOG_NOTICE,"readblock; tcpwrite error: %s",strerr(errno));
55 return -1;
56 }
57 for (;;) {
58 uint32_t cmd,l;
59 uint64_t t64;
60 uint16_t blockno,blockoffset;
61 uint32_t breq,blocksize,blockcrc;
62 if (tcptoread(fd,ibuff,8,CSMSECTIMEOUT)!=8) {
63 syslog(LOG_NOTICE,"readblock; tcpread error: %s",strerr(errno));
64 return -1;
65 }
66 rptr = ibuff;
67 cmd = get32bit(&rptr);
68 l = get32bit(&rptr);
69 if (cmd==CSTOCL_READ_STATUS) {
70 if (l!=9) {
71 syslog(LOG_NOTICE,"readblock; READ_STATUS incorrect message size (%"PRIu32"/9)",l);
72 return -1;
73 }
74 if (tcptoread(fd,ibuff,9,CSMSECTIMEOUT)!=9) {
75 syslog(LOG_NOTICE,"readblock; READ_STATUS tcpread error: %s",strerr(errno));
76 return -1;
77 }
78 rptr = ibuff;
79 t64 = get64bit(&rptr);
80 if (*rptr!=0) {
81 syslog(LOG_NOTICE,"readblock; READ_STATUS status: %s",mfsstrerr(*rptr));
82 return -1;
83 }
84 if (t64!=chunkid) {
85 syslog(LOG_NOTICE,"readblock; READ_STATUS incorrect chunkid (got:%"PRIu64" expected:%"PRIu64")",t64,chunkid);
86 return -1;
87 }
88 if (size!=0) {
89 syslog(LOG_NOTICE,"readblock; READ_STATUS incorrect data size (left: %"PRIu32")",size);
90 return -1;
91 }
92 return 0;
93 } else if (cmd==CSTOCL_READ_DATA) {
94 if (l<20) {
95 syslog(LOG_NOTICE,"readblock; READ_DATA incorrect message size (%"PRIu32"/>=20)",l);
96 return -1;
97 }
98 if (tcptoread(fd,ibuff,20,CSMSECTIMEOUT)!=20) {
99 syslog(LOG_NOTICE,"readblock; READ_DATA tcpread error: %s",strerr(errno));
100 return -1;
101 }
102 rptr = ibuff;
103 t64 = get64bit(&rptr);
104 if (t64!=chunkid) {
105 syslog(LOG_NOTICE,"readblock; READ_DATA incorrect chunkid (got:%"PRIu64" expected:%"PRIu64")",t64,chunkid);
106 return -1;
107 }
108 blockno = get16bit(&rptr);
109 blockoffset = get16bit(&rptr);
110 blocksize = get32bit(&rptr);
111 blockcrc = get32bit(&rptr);
112 if (l!=20+blocksize) {
113 syslog(LOG_NOTICE,"readblock; READ_DATA incorrect message size (%"PRIu32"/%"PRIu32")",l,20+blocksize);
114 return -1;
115 }
116 if (blocksize==0) {
117 syslog(LOG_NOTICE,"readblock; READ_DATA empty block");
118 return -1;
119 }
120 if (blockno!=(offset>>MFSBLOCKBITS)) {
121 syslog(LOG_NOTICE,"readblock; READ_DATA incorrect block number (got:%"PRIu16" expected:%"PRIu32")",blockno,(offset>>MFSBLOCKBITS));
122 return -1;
123 }
124 if (blockoffset!=(offset&MFSBLOCKMASK)) {
125 syslog(LOG_NOTICE,"readblock; READ_DATA incorrect block offset (got:%"PRIu16" expected:%"PRIu32")",blockoffset,(offset&MFSBLOCKMASK));
126 return -1;
127 }
128 breq = MFSBLOCKSIZE - (uint32_t)blockoffset;
129 if (size<breq) {
130 breq=size;
131 }
132 if (blocksize!=breq) {
133 syslog(LOG_NOTICE,"readblock; READ_DATA incorrect block size (got:%"PRIu32" expected:%"PRIu32")",blocksize,breq);
134 return -1;
135 }
136 if (tcptoread(fd,buff,blocksize,CSMSECTIMEOUT)!=(int32_t)blocksize) {
137 syslog(LOG_NOTICE,"readblock; READ_DATA tcpread error: %s",strerr(errno));
138 return -1;
139 }
140 if (blockcrc!=mycrc32(0,buff,blocksize)) {
141 syslog(LOG_NOTICE,"readblock; READ_DATA crc checksum error");
142 return -1;
143 }
144 offset+=blocksize;
145 size-=blocksize;
146 buff+=blocksize;
147 } else if (cmd==ANTOAN_NOP) {
148 if (l!=0) {
149 syslog(LOG_NOTICE,"readblock; NOP incorrect message size (%"PRIu32"/0)",l);
150 return -1;
151 }
152 } else if (cmd==ANTOAN_UNKNOWN_COMMAND || cmd==ANTOAN_BAD_COMMAND_SIZE) {
153 syslog(LOG_NOTICE,"readblock; got UNKNOWN_COMMAND/BAD_COMMAND_SIZE !!!");
154 return -1;
155 } else {
156 syslog(LOG_NOTICE,"readblock; unknown message");
157 return -1;
158 }
159 }
160 return 0;
161 }
162 /*
163 int cs_writestatus(int fd,uint64_t chunkid,uint32_t writeid) {
164 uint8_t ibuff[21];
165 const uint8_t *ptr;
166 uint32_t t32;
167 uint64_t t64;
168 if (tcptoread(fd,ibuff,21,CSMSECTIMEOUT)!=21) {
169 syslog(LOG_NOTICE,"writestatus; WRITE_STATUS tcpread error: %s",strerr(errno));
170 return -1;
171 }
172 ptr = ibuff;
173 t32 = get32bit(&ptr);
174 if (t32!=CSTOCL_WRITE_STATUS) {
175 syslog(LOG_NOTICE,"writestatus; WRITE_STATUS unknown message (%"PRIu32")",t32);
176 return -1;
177 }
178 t32 = get32bit(&ptr);
179 if (t32!=13) {
180 syslog(LOG_NOTICE,"writestatus; WRITE_STATUS incorrect message size (%"PRIu32"/13)",t32);
181 return -1;
182 }
183 t64 = get64bit(&ptr);
184 t32 = get32bit(&ptr);
185 if (*ptr!=0) {
186 syslog(LOG_NOTICE,"writestatus; WRITE_STATUS status: %s",mfsstrerr(*ptr));
187 return -1;
188 }
189 if (t64!=chunkid) {
190 syslog(LOG_NOTICE,"writestatus; WRITE_STATUS incorrect chunkid (got:%"PRIu64" expected:%"PRIu64")",t64,chunkid);
191 return -1;
192 }
193 if (t32!=writeid) {
194 syslog(LOG_NOTICE,"writestatus; WRITE_STATUS incorrect writeid (got:%"PRIu32" expected:%"PRIu32")",t32,writeid);
195 return -1;
196 }
197 return 0;
198 }
199
200 int cs_writeinit(int fd,const uint8_t *chain,uint32_t chainsize,uint64_t chunkid,uint32_t version) {
201 uint8_t *ptr,*ibuff;
202 uint32_t psize;
203 psize = 12+chainsize;
204 ibuff = malloc(8+psize);
205 if (ibuff==NULL) {
206 syslog(LOG_NOTICE,"writestatus; WRITE_INIT out of memory");
207 return -1;
208 }
209 ptr = ibuff;
210 put32bit(&ptr,CLTOCS_WRITE);
211 put32bit(&ptr,psize);
212 put64bit(&ptr,chunkid);
213 put32bit(&ptr,version);
214 memcpy(ptr,chain,chainsize);
215 psize+=8;
216 if (tcptowrite(fd,ibuff,psize,CSMSECTIMEOUT)!=(int32_t)psize) {
217 free(ibuff);
218 syslog(LOG_NOTICE,"writestatus; WRITE_INIT tcpwrite error: %s",strerr(errno));
219 return -1;
220 }
221 free(ibuff);
222 return cs_writestatus(fd,chunkid,0); // wait for connect status
223 }
224
225 int cs_writeblock(int fd,uint64_t chunkid,uint32_t writeid,uint16_t blockno,uint16_t offset,uint32_t size,uint8_t *buff) {
226 uint8_t *ptr,ibuff[32];
227 uint32_t crc,psize;
228 ptr = ibuff;
229 put32bit(&ptr,CLTOCS_WRITE_DATA);
230 psize = 24+size;
231 put32bit(&ptr,psize);
232 put64bit(&ptr,chunkid);
233 put32bit(&ptr,writeid);
234 put16bit(&ptr,blockno);
235 put16bit(&ptr,offset);
236 put32bit(&ptr,size);
237 crc = mycrc32(0,buff,size);
238 put32bit(&ptr,crc);
239 if (tcptowrite(fd,ibuff,32,CSMSECTIMEOUT)!=32) {
240 syslog(LOG_NOTICE,"writestatus; WRITE_DATA tcpwrite error: %s",strerr(errno));
241 return -1;
242 }
243 if (tcptowrite(fd,buff,size,CSMSECTIMEOUT)!=(int32_t)size) {
244 syslog(LOG_NOTICE,"writestatus; WRITE_DATA tcpwrite error: %s",strerr(errno));
245 return -1;
246 }
247 return 0;
248 }
249 */
250