Skip to content

Commit 9285dfd

Browse files
authored
Merge pull request #8 from Oldes/checksum-port
FEAT: CHECKSUM implemented also as a scheme (so one can do incremental computation)
2 parents e8a8824 + f9f2aeb commit 9285dfd

14 files changed

+539
-225
lines changed

src/core/c-port.c

+2-1
Original file line numberDiff line numberDiff line change
@@ -510,7 +510,7 @@ xx*/ REBINT Wait_Device(REBREQ *req, REBCNT timeout)
510510
**
511511
***********************************************************************/
512512

513-
#define MAX_SCHEMES 10 // max native schemes
513+
#define MAX_SCHEMES 11 // max native schemes
514514

515515
typedef struct rebol_scheme_actions {
516516
REBCNT sym;
@@ -625,6 +625,7 @@ SCHEME_ACTIONS *Scheme_Actions; // Initial Global (not threaded)
625625
Init_TCP_Scheme();
626626
Init_UDP_Scheme();
627627
Init_DNS_Scheme();
628+
Init_Checksum_Scheme();
628629
#ifndef MIN_OS
629630
Init_Clipboard_Scheme();
630631
#endif

src/core/m-series.c

-1
Original file line numberDiff line numberDiff line change
@@ -127,7 +127,6 @@
127127
Prior_Expand[n] = series;
128128
}
129129
Prior_Expand[0] = (REBSER*)n; // start next search here
130-
//#endif
131130
Prop_Series(newser, series);
132131
//ENABLE_GC;
133132

src/core/p-checksum.c

+221
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,221 @@
1+
/***********************************************************************
2+
**
3+
** REBOL [R3] Language Interpreter and Run-time Environment
4+
**
5+
** Copyright 2012 REBOL Technologies
6+
** REBOL is a trademark of REBOL Technologies
7+
**
8+
** Licensed under the Apache License, Version 2.0 (the "License");
9+
** you may not use this file except in compliance with the License.
10+
** You may obtain a copy of the License at
11+
**
12+
** http://www.apache.org/licenses/LICENSE-2.0
13+
**
14+
** Unless required by applicable law or agreed to in writing, software
15+
** distributed under the License is distributed on an "AS IS" BASIS,
16+
** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17+
** See the License for the specific language governing permissions and
18+
** limitations under the License.
19+
**
20+
************************************************************************
21+
**
22+
** Module: p-checksum.c
23+
** Summary: Checksum port interface
24+
** Section: ports
25+
** Author: Oldes
26+
** Notes:
27+
**
28+
***********************************************************************/
29+
30+
#include "sys-core.h"
31+
#include "reb-net.h"
32+
#include "sys-md5.h"
33+
#include "sys-sha1.h"
34+
#include "sys-sha256.h"
35+
36+
37+
/***********************************************************************
38+
**
39+
*/ static void Init_sizes(REBVAL *method, int *blk, int *ctx)
40+
/*
41+
***********************************************************************/
42+
{
43+
switch (VAL_WORD_CANON(method)) {
44+
case SYM_MD5:
45+
*ctx = sizeof(MD5_CTX);
46+
*blk = MD5_DIGEST_LENGTH;
47+
break;
48+
case SYM_SHA1:
49+
*ctx = sizeof(SHA_CTX);
50+
*blk = SHA_DIGEST_LENGTH;
51+
break;
52+
case SYM_SHA256:
53+
*ctx = sizeof(SHA256_CTX);
54+
*blk = SHA256_BLOCK_SIZE;
55+
return;
56+
default:
57+
*ctx = *blk = 0;
58+
break;
59+
}
60+
}
61+
62+
/***********************************************************************
63+
**
64+
*/ static REBOOL Checksum_Open(REBSER *port, REBVAL *method, int ctx_size)
65+
/*
66+
***********************************************************************/
67+
{
68+
REBVAL *data = BLK_SKIP(port, STD_PORT_DATA);
69+
REBVAL *ctx = BLK_SKIP(port, STD_PORT_LOCALS);
70+
71+
if(!IS_BINARY(ctx)) {
72+
SET_BINARY(ctx, Make_Binary(ctx_size));
73+
PROTECT_SERIES(VAL_SERIES(ctx));
74+
} else {
75+
CLEAR(VAL_BIN(ctx), VAL_TAIL(ctx));
76+
}
77+
VAL_TAIL(ctx) = ctx_size;
78+
switch (VAL_WORD_CANON(method)) {
79+
case SYM_MD5:
80+
MD5_Init((MD5_CTX*)VAL_BIN(ctx));
81+
return TRUE;
82+
case SYM_SHA1:
83+
SHA1_Init((SHA_CTX*)VAL_BIN(ctx));
84+
return TRUE;
85+
case SYM_SHA256:
86+
SHA256_Init((SHA256_CTX*)VAL_BIN(ctx));
87+
return TRUE;
88+
}
89+
return FALSE;
90+
}
91+
92+
/***********************************************************************
93+
**
94+
*/ static int Checksum_Actor(REBVAL *ds, REBSER *port, REBCNT action)
95+
/*
96+
***********************************************************************/
97+
{
98+
REBVAL *spec;
99+
REBVAL *method;
100+
REBREQ *req;
101+
REBVAL *arg;
102+
REBVAL *data;
103+
REBVAL *ctx;
104+
REBYTE *temp;
105+
106+
Validate_Port(port, action);
107+
108+
spec = BLK_SKIP(port, STD_PORT_SPEC);
109+
if (!IS_OBJECT(spec)) Trap1(RE_INVALID_SPEC, spec);
110+
method = Obj_Value(spec, STD_PORT_SPEC_HEAD_REF);
111+
if (!method || !IS_WORD(method)) Trap1(RE_INVALID_SPEC, spec);
112+
113+
*D_RET = *D_ARG(1);
114+
115+
req = Use_Port_State(port, RDI_CHECKSUM, sizeof(REBREQ));
116+
117+
data = BLK_SKIP(port, STD_PORT_DATA); //will hold result
118+
ctx = BLK_SKIP(port, STD_PORT_LOCALS);
119+
int ctx_size = 0, blk_size = 0;
120+
121+
Init_sizes(method, &blk_size, &ctx_size);
122+
123+
if(ctx_size == 0) Trap1(RE_INVALID_SPEC, method);
124+
125+
switch (action) {
126+
case A_WRITE:
127+
if (!IS_OPEN(req)) {
128+
Checksum_Open(port, method, ctx_size);
129+
SET_OPEN(req);
130+
}
131+
arg = D_ARG(2);
132+
switch (VAL_WORD_CANON(method)) {
133+
case SYM_MD5:
134+
MD5_Update((MD5_CTX*)VAL_BIN(ctx), VAL_BIN_DATA(arg), VAL_TAIL(arg) - VAL_INDEX(arg));
135+
break;
136+
case SYM_SHA1:
137+
SHA1_Update((SHA_CTX*)VAL_BIN(ctx), VAL_BIN_DATA(arg), VAL_TAIL(arg) - VAL_INDEX(arg));
138+
break;
139+
case SYM_SHA256:
140+
SHA256_Update((SHA256_CTX*)VAL_BIN(ctx), VAL_BIN_DATA(arg), VAL_TAIL(arg) - VAL_INDEX(arg));
141+
break;
142+
}
143+
break;
144+
case A_READ:
145+
case A_UPDATE:
146+
if (!IS_OPEN(req)) return R_NONE;
147+
148+
if (!IS_BINARY(data)) {
149+
SET_BINARY(data, Make_Binary(blk_size));
150+
VAL_TAIL(data) = blk_size;
151+
}
152+
else {
153+
if (blk_size > SERIES_REST(VAL_SERIES(data)) - VAL_INDEX(data)) {
154+
Expand_Series(VAL_BIN(data), AT_TAIL, blk_size - VAL_TAIL(data));
155+
}
156+
if (VAL_TAIL(data) < VAL_INDEX(data) + blk_size) {
157+
VAL_TAIL(data) = VAL_INDEX(data) + blk_size;
158+
}
159+
}
160+
161+
//using copy so READ will not destroy intermediate context state by calling *_Final
162+
memcpy(DS_TOP, VAL_BIN(ctx), ctx_size);
163+
164+
switch (VAL_WORD_CANON(method)) {
165+
case SYM_MD5:
166+
MD5_Final(VAL_BIN_DATA(data), (MD5_CTX*)DS_TOP);
167+
break;
168+
case SYM_SHA1:
169+
SHA1_Final(VAL_BIN_DATA(data), (SHA_CTX*)DS_TOP);
170+
break;
171+
case SYM_SHA256:
172+
SHA256_Final(VAL_BIN_DATA(data), (SHA256_CTX*)DS_TOP);
173+
break;
174+
}
175+
if(action == A_READ) *D_RET = *data;
176+
return R_RET;
177+
178+
case A_OPEN:
179+
if (IS_OPEN(req)) return R_RET;
180+
if (Checksum_Open(port, method, ctx_size)) {
181+
SET_OPEN(req);
182+
} else {
183+
//@@ throw an error?
184+
//Trap_Port(RE_CANNOT_OPEN, port, 0);
185+
return R_FALSE;
186+
}
187+
break;
188+
189+
case A_CLOSE:
190+
if (IS_OPEN(req)) {
191+
if (IS_BINARY(ctx)) {
192+
CLEAR(VAL_BIN(ctx), ctx_size);
193+
VAL_TAIL(ctx) = 0;
194+
}
195+
SET_NONE(data);
196+
SET_CLOSED(req);
197+
}
198+
break;
199+
200+
case A_OPENQ:
201+
if (IS_OPEN(req)) return R_TRUE;
202+
return R_FALSE;
203+
204+
default:
205+
Trap_Action(REB_PORT, action);
206+
}
207+
return R_RET;
208+
}
209+
210+
211+
/***********************************************************************
212+
**
213+
*/ void Init_Checksum_Scheme(void)
214+
/*
215+
***********************************************************************/
216+
{
217+
Register_Scheme(SYM_CHECKSUM, 0, Checksum_Actor);
218+
}
219+
220+
/* DEFINE_DEV would normally be in os/dev-checksum.c but I'm not using it so it is here */
221+
DEFINE_DEV(Dev_Checksum, "Checksum", 1, NULL, RDC_MAX, 0);

0 commit comments

Comments
 (0)