1use std::collections::HashMap;
4use std::ffi::CString;
5use std::io::{Read, Write};
6use std::os::unix::net::UnixStream;
7use std::time::Duration;
8
9use superfluid_abi::{
10 op_state, Artifact, CapabilityReq, StrategyRegistration, TapSpec,
11 TokenRange, RecordArena, Status,
12};
13use superfluid_engine::{Engine, StageOutput};
14use superfluid_proto::envelope::FrameClass;
15use superfluid_proto::handshake::{negotiate, Hello, HelloAckW};
16use superfluid_proto::linkw::{self, msg_type};
17use superfluid_proto::{encode_frame, Frame, FrameDecoder};
18use superfluid_shm::{
19 fdpass, ControlSegment, RingRole, SharedRing, SharedRings, ShmSegment, CONTROL_TAG, LOGITS_RING,
20 TOKEN_RING_IN, TOKEN_RING_OUT,
21};
22
23use crate::materialize::{
24 desc_to_msg, events_to_msg, match_result_to_msg, materialize_plan, token_ref_from_msg,
25};
26use crate::WorkerError;
27
28pub const PROTO_VERSION: u16 = 8;
29
30pub const TOKEN_OUT_SLOTS: u32 = 256;
34
35pub fn default_ring_specs() -> Vec<linkw::RingSpec> {
36 vec![
37 linkw::RingSpec {
38 ring_id: TOKEN_RING_IN,
39 kind: linkw::RingKind::Tokens,
40 slot_bytes: 16 + 4096 * 4,
41 slots: 64,
42 },
43 linkw::RingSpec {
44 ring_id: TOKEN_RING_OUT,
45 kind: linkw::RingKind::Tokens,
46 slot_bytes: 16 + 1024 * 4,
47 slots: TOKEN_OUT_SLOTS,
48 },
49 linkw::RingSpec {
50 ring_id: LOGITS_RING,
51 kind: linkw::RingKind::Logits,
52 slot_bytes: 16 + 64 * 4,
53 slots: 32,
54 },
55 ]
56}
57
58pub struct WorkerConfig {
59 pub engine_bundle_hash: [u8; 32],
60}
61
62enum OpBinding {
63 Export { buf_id: u64 },
64 Import,
65}
66
67pub struct WorkerServer<E: Engine> {
68 engine: E,
69 cfg: WorkerConfig,
70 frames: UnixStream,
71 fd_channel: UnixStream,
72 seq: u64,
73 rings: Option<SharedRings>,
74 pending_rings: HashMap<u32, SharedRing>,
75 pending_control: Option<ControlSegment>,
76 ring_specs: Vec<linkw::RingSpec>,
77 bufs: HashMap<u64, ShmSegment>,
78 pending_buf_release: std::collections::HashSet<u64>,
79 open_ops: HashMap<u64, OpBinding>,
80 op_window: usize,
81 decoder: FrameDecoder<fn(u16) -> bool>,
82 pending: std::collections::VecDeque<Frame>,
83 handshaken: bool,
84 chosen_version: u16,
85 last_mem: linkw::MemCountersMsg,
86}
87
88struct EmitSink<'a> {
89 frames: &'a mut UnixStream,
90 seq: &'a mut u64,
91 ok: bool,
92}
93
94unsafe extern "C" fn emit_tramp(
97 user: *mut std::ffi::c_void,
98 lane_tag: u64,
99 tokens: *const u32,
100 n_tokens: u32,
101) {
102 if user.is_null() || n_tokens == 0 {
103 return;
104 }
105 let sink = unsafe { &mut *(user as *mut EmitSink) };
108 if !sink.ok {
109 return;
110 }
111 if tokens.is_null() {
112 sink.ok = false;
113 return;
114 }
115 let toks = unsafe { std::slice::from_raw_parts(tokens, n_tokens as usize) };
118 let sent = std::panic::catch_unwind(std::panic::AssertUnwindSafe(|| {
119 let msg = linkw::TickEmitMsg { lane_tag, tokens: toks.to_vec() };
120 postcard::to_stdvec(&msg).is_ok_and(|p| {
121 send_frame(sink.frames, sink.seq, msg_type::TICK_EMIT, 0, &p).is_ok()
122 })
123 }));
124 sink.ok = sent.unwrap_or(false);
125}
126
127fn send_frame(
128 frames: &mut UnixStream,
129 seq: &mut u64,
130 msg_type: u16,
131 correlation: u64,
132 payload: &[u8],
133) -> Result<(), WorkerError> {
134 let class = if msg_type & 0x8000 != 0 {
135 FrameClass::Droppable
136 } else {
137 FrameClass::Required
138 };
139 let bytes = encode_frame(PROTO_VERSION, msg_type, *seq, correlation, class, payload)?;
140 *seq += 1;
141 frames.write_all(&bytes)?;
142 Ok(())
143}
144
145fn poll_transcribe_cancel(
146 frames: &mut UnixStream,
147 decoder: &mut FrameDecoder<fn(u16) -> bool>,
148 pending: &mut std::collections::VecDeque<Frame>,
149) -> bool {
150 if frames.set_nonblocking(true).is_err() {
151 return false;
152 }
153 let mut buf = [0u8; 64 * 1024];
154 let read = frames.read(&mut buf);
155 if frames.set_nonblocking(false).is_err() {
156 return true;
157 }
158 match read {
159 Ok(0) => return true,
160 Ok(n) => decoder.feed(&buf[..n]),
161 Err(e)
162 if e.kind() == std::io::ErrorKind::WouldBlock
163 || e.kind() == std::io::ErrorKind::TimedOut => {}
164 Err(_) => return true,
165 }
166 let mut cancel = false;
167 loop {
168 match decoder.decode_next() {
169 Ok(Some(frame)) => {
170 if frame.msg_type == msg_type::TRANSCRIBE_CANCEL {
171 cancel = true;
172 } else {
173 pending.push_back(frame);
174 }
175 }
176 Ok(None) => return cancel,
177 Err(_) => return true,
178 }
179 }
180}
181
182impl<E: Engine> WorkerServer<E> {
183 pub fn new(engine: E, cfg: WorkerConfig, frames: UnixStream, fd_channel: UnixStream) -> Self {
184 WorkerServer {
185 engine,
186 cfg,
187 frames,
188 fd_channel,
189 seq: 1,
190 rings: None,
191 pending_rings: HashMap::new(),
192 pending_control: None,
193 ring_specs: default_ring_specs(),
194 bufs: HashMap::new(),
195 pending_buf_release: std::collections::HashSet::new(),
196 open_ops: HashMap::new(),
197 op_window: 16,
198 decoder: FrameDecoder::new(linkw::is_known_type as fn(u16) -> bool),
199 pending: std::collections::VecDeque::new(),
200 handshaken: false,
201 chosen_version: 0,
202 last_mem: zero_mem(),
203 }
204 }
205
206 pub fn with_ring_specs(mut self, specs: Vec<linkw::RingSpec>) -> Self {
207 self.ring_specs = specs;
208 self
209 }
210
211 pub fn serve(mut self) -> Result<(), WorkerError> {
212 self.frames
213 .set_read_timeout(Some(Duration::from_millis(5)))?;
214 let mut buf = [0u8; 64 * 1024];
215 loop {
216 while let Some(frame) = self.pending.pop_front() {
217 self.dispatch(frame)?;
218 }
219 match self.frames.read(&mut buf) {
220 Ok(0) => return Ok(()),
221 Ok(n) => self.decoder.feed(&buf[..n]),
222 Err(e)
223 if e.kind() == std::io::ErrorKind::WouldBlock
224 || e.kind() == std::io::ErrorKind::TimedOut => {}
225 Err(e) => return Err(e.into()),
226 }
227 while let Some(frame) = self.decoder.decode_next()? {
228 self.dispatch(frame)?;
229 }
230 self.engine.pump();
231 self.flush_op_completions()?;
232 }
233 }
234
235 fn send(&mut self, msg_type: u16, correlation: u64, payload: &[u8]) -> Result<(), WorkerError> {
236 send_frame(
237 &mut self.frames,
238 &mut self.seq,
239 msg_type,
240 correlation,
241 payload,
242 )
243 }
244
245 fn reply<T: serde::Serialize>(
246 &mut self,
247 msg_type: u16,
248 correlation: u64,
249 msg: &T,
250 ) -> Result<(), WorkerError> {
251 let payload = postcard::to_stdvec(msg)?;
252 self.send(msg_type, correlation, &payload)
253 }
254
255 fn flush_op_completions(&mut self) -> Result<(), WorkerError> {
256 let handles: Vec<u64> = self.open_ops.keys().copied().collect();
257 for op in handles {
258 let st = match self.engine.op_poll(op) {
259 Ok(s) => s,
260 Err(_) => continue,
261 };
262 if st.state == op_state::PENDING || st.state == op_state::RUNNING {
263 continue;
264 }
265 let binding = self.open_ops.remove(&op).expect("present");
266 self.finalize_op(op, binding, st.state, st.error, st.bytes_moved)?;
267 }
268 Ok(())
269 }
270
271 fn finalize_op(
272 &mut self,
273 op: u64,
274 binding: OpBinding,
275 state: u8,
276 error: u32,
277 bytes_moved: u64,
278 ) -> Result<(), WorkerError> {
279 if state == op_state::DONE {
280 if let OpBinding::Export { buf_id } = binding {
281 if let Some(payload) = self.engine.take_op_output(op) {
282 if let Some(seg) = self.bufs.get(&buf_id) {
283 let _ = seg.write_at(0, &payload);
284 }
285 }
286 }
287 }
288 self.reply(
289 msg_type::STATE_OP_DONE,
290 0,
291 &linkw::StateOpDoneMsg {
292 op_handle: op,
293 state,
294 error,
295 bytes_moved,
296 },
297 )?;
298 if let OpBinding::Export { buf_id } = binding {
299 if self.pending_buf_release.remove(&buf_id) {
300 self.bufs.remove(&buf_id);
301 }
302 }
303 Ok(())
304 }
305
306 fn dispatch(&mut self, frame: Frame) -> Result<(), WorkerError> {
307 let corr = frame.seq;
308 if !self.handshaken && frame.msg_type != msg_type::HELLO {
309 return Err(WorkerError::Protocol("message before handshake"));
310 }
311 if self.handshaken && frame.proto_version != self.chosen_version {
312 return Err(WorkerError::Protocol(
313 "frame version differs from the negotiated version",
314 ));
315 }
316 match frame.msg_type {
317 msg_type::HELLO => {
318 let hello: Hello = postcard::from_bytes(&frame.payload)?;
319 let chosen = negotiate(hello.proto_versions, (PROTO_VERSION, PROTO_VERSION))
320 .ok_or(WorkerError::Protocol("no common proto version"))?;
321 let descs: Vec<_> = self.engine.state_spaces().iter().map(desc_to_msg).collect();
322 let ack = HelloAckW {
323 chosen_version: chosen,
324 engine_bundle_hash: self.cfg.engine_bundle_hash,
325 capabilities: self.engine.capability_descriptor().unwrap_or_default(),
326 state_space_descriptors: descs,
327 registered_strategies: Vec::new(),
328 limits: linkw::LinkWLimits {
329 max_frame: superfluid_proto::MAX_FRAME,
330 op_window: self.op_window as u32,
331 ring_specs: self.ring_specs.clone(),
332 },
333 kv_bits: self.engine.kv_bits(),
334 };
335 self.handshaken = true;
336 self.chosen_version = chosen;
337 self.reply(msg_type::HELLO_ACK_W, corr, &ack)
338 }
339 msg_type::RING_ATTACH => {
340 let msg: linkw::RingAttachMsg = postcard::from_bytes(&frame.payload)?;
341 let spec = self
342 .ring_specs
343 .iter()
344 .find(|s| s.ring_id == msg.ring_id)
345 .copied()
346 .ok_or(WorkerError::Protocol("attach for unknown ring id"))?;
347 if msg.layout != spec {
348 return Err(WorkerError::Protocol("ring layout disagrees with spec"));
349 }
350 let (fd, tag) = fdpass::recv_fd(&self.fd_channel)?;
351 if tag != msg.ring_id as u64 {
352 return Err(WorkerError::Protocol("fd tag does not match ring id"));
353 }
354 let seg =
355 ShmSegment::from_fd(fd, SharedRing::required_len(spec.slots, spec.slot_bytes))?;
356 let role = if msg.ring_id == TOKEN_RING_IN {
357 RingRole::Reader
358 } else {
359 RingRole::Writer
360 };
361 let ring = SharedRing::attach(seg, msg.ring_id, spec.slots, spec.slot_bytes, role)?;
362 let attach = superfluid_engine::rings::RingAttachment {
363 ring_id: msg.ring_id,
364 kind: match spec.kind {
365 linkw::RingKind::Tokens => superfluid_abi::ring_kind::TOKENS,
366 linkw::RingKind::Logits => superfluid_abi::ring_kind::LOGITS,
367 },
368 role: if msg.ring_id == TOKEN_RING_IN {
369 superfluid_abi::ring_role::ENGINE_READS
370 } else {
371 superfluid_abi::ring_role::ENGINE_WRITES
372 },
373 slots: spec.slots,
374 slot_bytes: spec.slot_bytes,
375 base: ring.base_ptr(),
376 len: ring.seg_len(),
377 };
378 self.engine
379 .attach_ring(&attach)
380 .map_err(|_| WorkerError::Protocol("engine refused ring attachment"))?;
381 self.pending_rings.insert(msg.ring_id, ring);
382 if self.rings.is_none()
383 && [TOKEN_RING_IN, TOKEN_RING_OUT, LOGITS_RING]
384 .iter()
385 .all(|id| self.pending_rings.contains_key(id))
386 {
387 self.rings = Some(SharedRings {
388 token_in: self.pending_rings.remove(&TOKEN_RING_IN).expect("checked"),
389 token_out: self.pending_rings.remove(&TOKEN_RING_OUT).expect("checked"),
390 logits: self.pending_rings.remove(&LOGITS_RING).expect("checked"),
391 control: self.pending_control.take(),
392 });
393 }
394 self.reply(
395 msg_type::RING_ACK,
396 corr,
397 &linkw::RingAckMsg {
398 ring_id: msg.ring_id,
399 generation_base: 1,
400 },
401 )
402 }
403 msg_type::CONTROL_ATTACH => {
404 let msg: linkw::ControlAttachMsg = postcard::from_bytes(&frame.payload)?;
405 let (fd, tag) = fdpass::recv_fd(&self.fd_channel)?;
406 if tag != CONTROL_TAG {
407 return Err(WorkerError::Protocol("fd tag is not the control segment's"));
408 }
409 let control = ControlSegment::attach(ShmSegment::from_fd(fd, msg.bytes as usize)?)?;
410 match self.rings.as_mut() {
411 Some(rings) => rings.control = Some(control),
412 None => self.pending_control = Some(control),
413 }
414 self.reply(msg_type::CONTROL_ACK, corr, &linkw::ControlAckMsg { bytes: msg.bytes })
415 }
416 msg_type::TICK_SUBMIT => {
417 let msg: linkw::TickSubmitMsg = postcard::from_bytes(&frame.payload)?;
418 let Self { engine, frames, seq, rings, .. } = self;
419 let rings = rings
420 .as_mut()
421 .ok_or(WorkerError::Protocol("tick before ring attach"))?;
422 let (mut plan, arena) = materialize_plan(&msg.plan);
423 let mut sink = EmitSink { frames, seq, ok: true };
424 if msg.plan.flags & superfluid_abi::tick_flags::PARTIAL_EMITS != 0 {
425 plan.on_partial_emit = Some(emit_tramp);
426 plan.partial_emit_user = (&mut sink as *mut EmitSink).cast();
427 }
428 let result = match engine.tick(&plan, &arena, rings) {
429 Ok(ev) => linkw::TickResultMsg::Events(events_to_msg(ev)),
430 Err(s) => linkw::TickResultMsg::Rejected { status: s.raw() },
431 };
432 if let linkw::TickResultMsg::Events(ev) = &result {
433 self.last_mem = ev.mem;
434 let done: Vec<linkw::OpCompleteMsg> = ev.op_completions.clone();
435 for c in done {
436 if let Some(binding) = self.open_ops.remove(&c.op) {
437 self.finalize_op(c.op, binding, c.state, c.error, c.bytes_moved)?;
438 }
439 }
440 }
441 self.reply(msg_type::TICK_RESULT, corr, &result)
442 }
443 msg_type::MATCH_REQ => {
444 let msg: linkw::MatchReqMsg = postcard::from_bytes(&frame.payload)?;
445 let rings = self
446 .rings
447 .as_ref()
448 .ok_or(WorkerError::Protocol("match before ring attach"))?;
449 let span = token_ref_from_msg(&msg.span);
450 use superfluid_engine::Rings;
451 let tokens = rings
452 .read_tokens(&span)
453 .map_err(|_| WorkerError::Protocol("stale span in match"))?;
454 let res = self
455 .engine
456 .space_match_ref(msg.space_id, &span, &tokens, &msg.media_deps)
457 .map(match_result_to_msg)
458 .unwrap_or(linkw::MatchResMsg { spaces: Vec::new() });
459 self.reply(msg_type::MATCH_RES, corr, &res)
460 }
461 msg_type::SEED_ACQUIRE => {
462 let msg: linkw::SeedAcquireMsg = postcard::from_bytes(&frame.payload)?;
463 let rings = self
464 .rings
465 .as_ref()
466 .ok_or(WorkerError::Protocol("seed before ring attach"))?;
467 use superfluid_engine::Rings;
468 let span = token_ref_from_msg(&msg.span);
469 let grant = match rings.read_tokens(&span) {
470 Ok(tokens) => match self.engine.seed_acquire_ref(
471 &span,
472 &tokens,
473 msg.prefix_len,
474 msg.determinism_class,
475 ) {
476 Ok(handle) => linkw::SeedGrantMsg::Granted {
477 seed_handle: handle,
478 ttl_ms: 1000,
479 ttl_ticks: self.engine.seed_lease_ticks(),
480 },
481 Err(s) => linkw::SeedGrantMsg::Refused { status: s.raw() },
482 },
483 Err(_) => linkw::SeedGrantMsg::Refused {
484 status: Status::RejectBadRefGeneration.raw(),
485 },
486 };
487 self.reply(msg_type::SEED_GRANT, corr, &grant)
488 }
489 msg_type::SEED_RELEASE => {
490 let msg: linkw::SeedReleaseMsg = postcard::from_bytes(&frame.payload)?;
491 let _ = self.engine.seed_release(msg.seed_handle);
492 Ok(())
493 }
494 msg_type::STATE_OP_SUBMIT => {
495 let msg: linkw::StateOpSubmitMsg = postcard::from_bytes(&frame.payload)?;
496 let reply = if self.open_ops.len() >= self.op_window {
497 linkw::StateOpAcceptedMsg::Rejected {
498 status: Status::Busy.raw(),
499 }
500 } else {
501 self.submit_state_op(&msg.op)
502 };
503 self.reply(msg_type::STATE_OP_ACCEPTED, corr, &reply)
504 }
505 msg_type::OP_CANCEL => {
506 let msg: linkw::OpCancelMsg = postcard::from_bytes(&frame.payload)?;
507 let _ = self.engine.op_cancel(msg.op_handle);
508 Ok(())
509 }
510 msg_type::STATE_SYNC_REQ => {
511 let msg: linkw::StateSyncReqMsg = postcard::from_bytes(&frame.payload)?;
512 let res = self.state_sync(&msg);
513 self.reply(msg_type::STATE_SYNC_RES, corr, &res)
514 }
515 msg_type::STRATEGY_REGISTER => {
516 let msg: linkw::StrategyRegisterMsg = postcard::from_bytes(&frame.payload)?;
517 let res = self.register_strategy(&msg);
518 self.reply(msg_type::STRATEGY_GRANT, corr, &res)
519 }
520 msg_type::BUF_ALLOC => {
521 let _msg: linkw::BufAllocMsg = postcard::from_bytes(&frame.payload)?;
522 Ok(())
523 }
524 msg_type::BUF_ATTACH => {
525 let msg: linkw::BufAttachMsg = postcard::from_bytes(&frame.payload)?;
526 let (fd, tag) = fdpass::recv_fd(&self.fd_channel)?;
527 if tag != msg.buf_id {
528 return Err(WorkerError::Protocol("fd tag does not match buf id"));
529 }
530 let seg = ShmSegment::from_fd(fd, msg.len as usize)?;
531 self.bufs.insert(msg.buf_id, seg);
532 Ok(())
533 }
534 msg_type::BUF_RELEASE => {
535 let msg: linkw::BufReleaseMsg = postcard::from_bytes(&frame.payload)?;
536 let bound = self
537 .open_ops
538 .values()
539 .any(|b| matches!(b, OpBinding::Export { buf_id } if *buf_id == msg.buf_id));
540 if bound {
541 self.pending_buf_release.insert(msg.buf_id);
542 } else {
543 self.bufs.remove(&msg.buf_id);
544 }
545 Ok(())
546 }
547 msg_type::PING => {
548 let _msg: linkw::PingMsg = postcard::from_bytes(&frame.payload)?;
549 let pong = linkw::PongMsg {
550 queue_depth: self.open_ops.len() as u32,
551 mem: self.last_mem,
552 };
553 self.reply(msg_type::PONG, corr, &pong)
554 }
555 msg_type::DRAIN_REQ => {
556 while !self.open_ops.is_empty() {
557 self.engine.pump();
558 self.flush_op_completions()?;
559 }
560 self.reply(msg_type::DRAINED, corr, &linkw::DrainedMsg)
561 }
562 msg_type::TELEMETRY => Ok(()),
563 msg_type::TRANSCRIBE_CANCEL => Ok(()),
564 _ => Err(WorkerError::Protocol("unhandled required message")),
565 }
566 }
567
568 fn submit_state_op(&mut self, op: &linkw::StateOpKind) -> linkw::StateOpAcceptedMsg {
569 let result: Result<(u64, OpBinding), Status> = match *op {
570 linkw::StateOpKind::Snapshot {
571 sequence,
572 space_id,
573 boundary_pos,
574 buf_id,
575 sizing_gen,
576 } => {
577 let Some(seg) = self.bufs.get(&buf_id) else {
578 return linkw::StateOpAcceptedMsg::Rejected {
579 status: Status::UnknownHandle.raw(),
580 };
581 };
582 let len = seg.len() as u64;
583 self.engine
584 .space_snapshot(sequence, space_id, boundary_pos, len, sizing_gen)
585 .map(|h| (h, OpBinding::Export { buf_id }))
586 }
587 linkw::StateOpKind::Demote {
588 sequence,
589 space_id,
590 range,
591 encoding,
592 buf_id,
593 sizing_gen,
594 } => {
595 let Some(seg) = self.bufs.get(&buf_id) else {
596 return linkw::StateOpAcceptedMsg::Rejected {
597 status: Status::UnknownHandle.raw(),
598 };
599 };
600 let len = seg.len() as u64;
601 self.engine
602 .space_demote(
603 sequence,
604 space_id,
605 TokenRange {
606 start: range.start,
607 end: range.end,
608 },
609 encoding,
610 len,
611 sizing_gen,
612 )
613 .map(|h| (h, OpBinding::Export { buf_id }))
614 }
615 linkw::StateOpKind::Restore {
616 sequence,
617 space_id,
618 buf_id,
619 } => match self.read_sealed(buf_id) {
620 Ok(bytes) => self
621 .engine
622 .space_restore(sequence, space_id, &bytes)
623 .map(|h| (h, OpBinding::Import)),
624 Err(s) => Err(s),
625 },
626 linkw::StateOpKind::Promote {
627 sequence,
628 space_id,
629 range,
630 buf_id,
631 } => match self.read_sealed(buf_id) {
632 Ok(bytes) => self
633 .engine
634 .space_promote(
635 sequence,
636 space_id,
637 TokenRange {
638 start: range.start,
639 end: range.end,
640 },
641 &bytes,
642 )
643 .map(|h| (h, OpBinding::Import)),
644 Err(s) => Err(s),
645 },
646 };
647 match result {
648 Ok((handle, binding)) => {
649 self.open_ops.insert(handle, binding);
650 linkw::StateOpAcceptedMsg::Accepted { op_handle: handle }
651 }
652 Err(s) => linkw::StateOpAcceptedMsg::Rejected { status: s.raw() },
653 }
654 }
655
656 fn read_sealed(&self, buf_id: u64) -> Result<Vec<u8>, Status> {
657 const ENVELOPE_BYTES: usize = std::mem::size_of::<superfluid_abi::StateEnvelope>();
658 let seg = self.bufs.get(&buf_id).ok_or(Status::UnknownHandle)?;
659 if seg.len() < ENVELOPE_BYTES {
660 return Err(Status::EnvelopeMismatch);
661 }
662 let mut head = vec![0u8; ENVELOPE_BYTES];
663 seg.read_at(0, &mut head)
664 .map_err(|_| Status::EnvelopeMismatch)?;
665 let off = std::mem::offset_of!(superfluid_abi::StateEnvelope, payload_len);
666 let payload_len = u64::from_le_bytes(head[off..off + 8].try_into().expect("8 bytes"));
667 let payload_len = usize::try_from(payload_len).map_err(|_| Status::EnvelopeMismatch)?;
668 let total = ENVELOPE_BYTES
669 .checked_add(payload_len)
670 .ok_or(Status::EnvelopeMismatch)?;
671 if seg.len() < total {
672 return Err(Status::EnvelopeMismatch);
673 }
674 let mut out = vec![0u8; total];
675 seg.read_at(0, &mut out)
676 .map_err(|_| Status::EnvelopeMismatch)?;
677 Ok(out)
678 }
679
680 fn state_sync(&mut self, msg: &linkw::StateSyncReqMsg) -> linkw::StateSyncResMsg {
681 let result = match *msg {
682 linkw::StateSyncReqMsg::Fork {
683 parent_sequence,
684 flags,
685 } => self.engine.seq_fork(parent_sequence, flags).map(|child| {
686 linkw::StateSyncOkMsg::Fork {
687 child_sequence: child,
688 }
689 }),
690 linkw::StateSyncReqMsg::Trim {
691 sequence,
692 space_id,
693 new_len,
694 } => self
695 .engine
696 .space_trim(sequence, space_id, new_len)
697 .map(|()| linkw::StateSyncOkMsg::Trim),
698 linkw::StateSyncReqMsg::ExportSize {
699 sequence,
700 space_id,
701 range,
702 encoding,
703 } => self
704 .engine
705 .space_export_size(
706 sequence,
707 space_id,
708 TokenRange {
709 start: range.start,
710 end: range.end,
711 },
712 encoding,
713 )
714 .map(
715 |(required_bytes, sizing_gen)| linkw::StateSyncOkMsg::ExportSize {
716 required_bytes,
717 sizing_gen,
718 },
719 ),
720 linkw::StateSyncReqMsg::CacheEvict {
721 bytes_target,
722 ref policy,
723 } => self
724 .engine
725 .cache_evict(
726 policy.evictable_cache_classes,
727 policy.protected_quota_bytes,
728 policy.max_evict_bytes,
729 bytes_target,
730 )
731 .map(|bytes_freed| linkw::StateSyncOkMsg::CacheEvict { bytes_freed }),
732 linkw::StateSyncReqMsg::CacheEvictEntries { ref keys } => {
733 let raw: Vec<([u8; 32], [u8; 32])> =
734 keys.iter().map(|k| (k.compat_key, k.provenance_digest)).collect();
735 self.engine
736 .cache_evict_entries(&raw)
737 .map(|()| linkw::StateSyncOkMsg::CacheEvictEntries)
738 }
739 linkw::StateSyncReqMsg::SnapshotBoundary {
740 sequence,
741 space_id,
742 cap,
743 } => self
744 .engine
745 .space_snapshot_boundary(sequence, space_id, cap)
746 .map(|boundary| linkw::StateSyncOkMsg::SnapshotBoundary { boundary }),
747 linkw::StateSyncReqMsg::LaneSequence { lane_tag } => self
748 .engine
749 .lane_sequence(lane_tag)
750 .map(|sequence| linkw::StateSyncOkMsg::LaneSequence { sequence })
751 .ok_or(Status::UnknownHandle),
752 linkw::StateSyncReqMsg::CreateSequence => self
753 .engine
754 .create_sequence()
755 .map(|sequence| linkw::StateSyncOkMsg::CreateSequence { sequence }),
756 linkw::StateSyncReqMsg::FreeSequence { sequence } => self
757 .engine
758 .free_sequence(sequence)
759 .map(|()| linkw::StateSyncOkMsg::FreeSequence),
760 linkw::StateSyncReqMsg::CreateGrammarStructural { ref tag_json } => self
761 .engine
762 .grammar_create_structural(tag_json)
763 .map(|grammar_handle| linkw::StateSyncOkMsg::CreateGrammar { grammar_handle }),
764 linkw::StateSyncReqMsg::CreateGrammar { ref json_schema } => self
765 .engine
766 .grammar_create(json_schema)
767 .map(|grammar_handle| linkw::StateSyncOkMsg::CreateGrammar { grammar_handle }),
768 linkw::StateSyncReqMsg::FreeGrammar { grammar_handle } => self
769 .engine
770 .grammar_free(grammar_handle)
771 .map(|()| linkw::StateSyncOkMsg::FreeGrammar),
772 linkw::StateSyncReqMsg::CreateLogitBias { ref tokens, ref values } => {
773 let vals: Vec<f32> = values.iter().map(|b| f32::from_bits(*b)).collect();
774 self.engine
775 .logit_bias_create(tokens, &vals)
776 .map(|handle| linkw::StateSyncOkMsg::CreateLogitBias { handle })
777 }
778 linkw::StateSyncReqMsg::FreeLogitBias { handle } => self
779 .engine
780 .logit_bias_free(handle)
781 .map(|()| linkw::StateSyncOkMsg::FreeLogitBias),
782 linkw::StateSyncReqMsg::Embed { ref tokens } => self.engine.embed(tokens).map(|v| {
783 let mut bytes = Vec::with_capacity(v.len() * 4);
784 for f in v {
785 bytes.extend_from_slice(&f.to_le_bytes());
786 }
787 linkw::StateSyncOkMsg::Embed { embedding: bytes }
788 }),
789 linkw::StateSyncReqMsg::Transcribe {
790 ref audio_path,
791 ref language,
792 translate,
793 timestamps,
794 ref prompt,
795 stream,
796 } => {
797 let params = superfluid_engine::TranscribeParams {
798 language: language.clone(),
799 translate,
800 timestamps,
801 prompt: prompt.clone(),
802 };
803 let Self { engine, frames, seq, decoder, pending, .. } = self;
804 let mut sink = |start_ms: i32, end_ms: i32, text: &str| -> bool {
805 let msg = linkw::TranscribeSegmentMsg {
806 start_ms,
807 end_ms,
808 text: text.to_string(),
809 };
810 let sent = postcard::to_stdvec(&msg).is_ok_and(|p| {
811 send_frame(frames, seq, msg_type::TRANSCRIBE_SEGMENT, 0, &p).is_ok()
812 });
813 sent && !poll_transcribe_cancel(frames, decoder, pending)
814 };
815 if stream {
816 engine.transcribe(audio_path, ¶ms, Some(&mut sink))
817 } else {
818 engine.transcribe(audio_path, ¶ms, None)
819 }
820 }
821 .map(|t| linkw::StateSyncOkMsg::Transcribe {
822 text: t.text,
823 language: t.language,
824 duration_ms: t.duration_ms,
825 segments: t
826 .segments
827 .into_iter()
828 .map(|s| linkw::TranscriptSegmentMsg {
829 start_ms: s.start_ms,
830 end_ms: s.end_ms,
831 text: s.text,
832 avg_logprob_bits: s.avg_logprob.to_bits(),
833 no_speech_prob_bits: s.no_speech_prob.to_bits(),
834 compression_ratio_bits: s.compression_ratio.to_bits(),
835 temperature_bits: s.temperature.to_bits(),
836 })
837 .collect(),
838 }),
839 linkw::StateSyncReqMsg::LoraLoad { ref adapter_path } => self
840 .engine
841 .lora_load(adapter_path)
842 .map(|()| linkw::StateSyncOkMsg::LoraId { id: self.engine.lora_id() }),
843 linkw::StateSyncReqMsg::LoraUnload => self
844 .engine
845 .lora_unload()
846 .map(|()| linkw::StateSyncOkMsg::LoraId { id: self.engine.lora_id() }),
847 linkw::StateSyncReqMsg::LoraId => {
848 Ok(linkw::StateSyncOkMsg::LoraId { id: self.engine.lora_id() })
849 }
850 linkw::StateSyncReqMsg::Capabilities => Ok(linkw::StateSyncOkMsg::Capabilities {
851 json: self.engine.capability_descriptor().unwrap_or_default(),
852 }),
853 linkw::StateSyncReqMsg::ForwardStage {
854 ref tokens,
855 start_layer,
856 end_layer,
857 ref hidden_in,
858 } => self
859 .engine
860 .forward_stage(tokens, start_layer, end_layer, hidden_in.clone())
861 .map(|out| match out {
862 StageOutput::Hidden(h) => linkw::StateSyncOkMsg::ForwardStage {
863 hidden: Some(h),
864 token: None,
865 },
866 StageOutput::Token(t) => linkw::StateSyncOkMsg::ForwardStage {
867 hidden: None,
868 token: Some(t),
869 },
870 }),
871 linkw::StateSyncReqMsg::MediaProbe { ref image_path } => {
872 self.engine.media_probe(image_path).map(|i| linkw::StateSyncOkMsg::MediaProbe {
873 info: linkw::MediaInfoMsg {
874 n_tokens: i.n_tokens,
875 image_token_id: i.image_token_id,
876 boi_token_id: i.boi_token_id,
877 eoi_token_id: i.eoi_token_id,
878 preprocess_fp: i.preprocess_fp,
879 },
880 })
881 }
882 linkw::StateSyncReqMsg::MediaEncode { ref image_path } => {
883 self.engine
884 .media_encode(image_path)
885 .map(|(media_handle, i)| linkw::StateSyncOkMsg::MediaEncode {
886 media_handle,
887 info: linkw::MediaInfoMsg {
888 n_tokens: i.n_tokens,
889 image_token_id: i.image_token_id,
890 boi_token_id: i.boi_token_id,
891 eoi_token_id: i.eoi_token_id,
892 preprocess_fp: i.preprocess_fp,
893 },
894 })
895 }
896 linkw::StateSyncReqMsg::MediaRelease { media_handle } => self
897 .engine
898 .media_release(media_handle)
899 .map(|()| linkw::StateSyncOkMsg::MediaRelease),
900 linkw::StateSyncReqMsg::MediaBind {
901 lane_tag,
902 media_handle,
903 token_offset,
904 } => self
905 .engine
906 .media_bind(lane_tag, media_handle, token_offset)
907 .map(|()| linkw::StateSyncOkMsg::MediaBind),
908 linkw::StateSyncReqMsg::AdoptSequence { sequence, ref span } => {
909 use superfluid_engine::Rings;
910 let span_ref = token_ref_from_msg(span);
911 match self.rings.as_ref() {
912 None => Err(Status::RejectBadRefGeneration),
913 Some(rings) => match rings.read_tokens(&span_ref) {
914 Ok(tokens) => self
915 .engine
916 .seed_adopt_ref(sequence, &span_ref, &tokens)
917 .map(|seed_handle| linkw::StateSyncOkMsg::AdoptSequence { seed_handle }),
918 Err(_) => Err(Status::RejectBadRefGeneration),
919 },
920 }
921 }
922 linkw::StateSyncReqMsg::PublishSequence { sequence, ref span } => {
923 use superfluid_engine::Rings;
924 let span = token_ref_from_msg(span);
925 match self.rings.as_ref() {
926 None => Err(Status::RejectBadRefGeneration),
927 Some(rings) => match rings.read_tokens(&span) {
928 Ok(tokens) => self
929 .engine
930 .publish_sequence(sequence, &tokens)
931 .map(|()| linkw::StateSyncOkMsg::PublishSequence),
932 Err(_) => Err(Status::RejectBadRefGeneration),
933 },
934 }
935 }
936 linkw::StateSyncReqMsg::Unpublish { ref span } => {
937 use superfluid_engine::Rings;
938 let span = token_ref_from_msg(span);
939 match self.rings.as_ref() {
940 None => Err(Status::RejectBadRefGeneration),
941 Some(rings) => match rings.read_tokens(&span) {
942 Ok(tokens) => self.engine.unpublish(&tokens).map(|()| linkw::StateSyncOkMsg::Unpublish),
943 Err(_) => Err(Status::RejectBadRefGeneration),
944 },
945 }
946 }
947 };
948 match result {
949 Ok(ok) => linkw::StateSyncResMsg::Ok(ok),
950 Err(s) => linkw::StateSyncResMsg::Err { status: s.raw() },
951 }
952 }
953
954 fn register_strategy(&mut self, msg: &linkw::StrategyRegisterMsg) -> linkw::StrategyGrantMsg {
955 let strategy_id = CString::new(msg.strategy_id.as_str()).unwrap_or_default();
956 let impl_version = CString::new(msg.impl_version.as_str()).unwrap_or_default();
957 let load_paths: Vec<CString> = msg
958 .artifacts
959 .iter()
960 .map(|a| CString::new(a.load_path.as_str()).unwrap_or_default())
961 .collect();
962 let archs: Vec<CString> = msg
963 .target_archs
964 .iter()
965 .map(|a| CString::new(a.as_str()).unwrap_or_default())
966 .collect();
967 let mut arena = RecordArena::new();
968 let artifacts: Vec<Artifact> = msg
969 .artifacts
970 .iter()
971 .zip(&load_paths)
972 .map(|(a, p)| Artifact {
973 role: a.role,
974 _pad0: 0,
975 content_hash: a.content_hash,
976 byte_size: a.byte_size,
977 load_path: p.as_ptr(),
978 })
979 .collect();
980 let taps: Vec<TapSpec> = msg
981 .taps
982 .iter()
983 .map(|t| TapSpec {
984 layer: t.layer,
985 tensor: t.tensor,
986 dtype: t.dtype,
987 layout: t.layout,
988 })
989 .collect();
990 let capabilities: Vec<CapabilityReq> = msg
991 .capabilities
992 .iter()
993 .map(|c| CapabilityReq {
994 kind_id: c.kind_id,
995 _pad0: 0,
996 params: arena.push_records(&c.params),
997 })
998 .collect();
999 let arch_ptrs: Vec<u64> = archs.iter().map(|a| a.as_ptr() as u64).collect();
1000
1001 let reg = StrategyRegistration {
1002 struct_size: std::mem::size_of::<StrategyRegistration>() as u64,
1003 strategy_id: strategy_id.as_ptr(),
1004 impl_version: impl_version.as_ptr(),
1005 impl_hash: msg.impl_hash,
1006 config_hash: msg.config_hash,
1007 artifacts: arena.push_records(&artifacts),
1008 taps: arena.push_records(&taps),
1009 capabilities: arena.push_records(&capabilities),
1010 target_archs: arena.push_records(&arch_ptrs),
1011 kernel_caps_required: msg.kernel_caps_required,
1012 _pad0: 0,
1013 est_state_bytes: msg.est_state_bytes,
1014 claimed_exactness: msg.claimed_exactness,
1015 _pad1: [0; 3],
1016 rng_contract_version: msg.rng_contract_version,
1017 };
1018
1019 match self.engine.strategy_register(®) {
1020 Ok(grant) => {
1021 let bounds = superfluid_abi::ArenaBounds {
1022 base: 0,
1023 len: usize::MAX,
1024 };
1025 let certificates = unsafe {
1028 superfluid_abi::array::read_array::<superfluid_abi::ExactnessCert>(
1029 &grant.certificates,
1030 &bounds,
1031 )
1032 .map(|it| {
1033 it.map(|c| {
1034 let ids = superfluid_abi::array::read_array::<[u8; 32]>(
1035 &c.admissible_host_identities,
1036 &bounds,
1037 )
1038 .map(|h| h.collect())
1039 .unwrap_or_default();
1040 linkw::ExactnessCertMsg {
1041 cert_id: c.cert_id,
1042 exactness: c.exactness,
1043 sampling_modes: c.sampling_modes,
1044 param_domain: c.param_domain,
1045 grammar_allowed: c.grammar_allowed != 0,
1046 logit_bias_allowed: c.logit_bias_allowed != 0,
1047 verification_shape_class: c.verification_shape_class,
1048 admissible_host_identities: ids,
1049 }
1050 })
1051 .collect()
1052 })
1053 .unwrap_or_default()
1054 };
1055 let state_spaces = {
1056 unsafe {
1058 superfluid_abi::array::read_array::<superfluid_abi::StateSpaceDesc>(
1059 &grant.state_spaces,
1060 &bounds,
1061 )
1062 .map(|it| it.map(|d| desc_to_msg(&d)).collect())
1063 .unwrap_or_default()
1064 }
1065 };
1066 linkw::StrategyGrantMsg::Granted(linkw::StrategyGrantOkMsg {
1067 strategy_slot: grant.strategy_slot,
1068 certificates,
1069 state_spaces,
1070 reserved_bytes: grant.reserved_bytes,
1071 })
1072 }
1073 Err(s) => linkw::StrategyGrantMsg::Refused { status: s.raw() },
1074 }
1075 }
1076}
1077
1078fn zero_mem() -> linkw::MemCountersMsg {
1079 linkw::MemCountersMsg {
1080 allocated_bytes: 0,
1081 host_retained_bytes: 0,
1082 pool_blocks_total: 0,
1083 pool_blocks_used: 0,
1084 pool_bytes_evictable: 0,
1085 tentative_bytes: 0,
1086 }
1087}
1088
1089#[cfg(test)]
1090mod tests {
1091 use super::*;
1092
1093 #[test]
1094 fn the_emit_trampoline_refuses_null_pointers_from_the_engine() {
1095 let (mut frames, mut peer) = UnixStream::pair().unwrap();
1096 let mut seq = 1;
1097 let toks = [4u32, 5, 6];
1098 unsafe {
1101 emit_tramp(std::ptr::null_mut(), 7, toks.as_ptr(), 3);
1102 let mut sink = EmitSink { frames: &mut frames, seq: &mut seq, ok: true };
1103 emit_tramp((&mut sink as *mut EmitSink).cast(), 7, std::ptr::null(), 3);
1104 assert!(!sink.ok, "a null token pointer ends the partial emits");
1105 let mut sink = EmitSink { frames: &mut frames, seq: &mut seq, ok: true };
1106 emit_tramp((&mut sink as *mut EmitSink).cast(), 7, toks.as_ptr(), 3);
1107 assert!(sink.ok, "a good emit is sent");
1108 }
1109 drop(frames);
1110 let mut sent = Vec::new();
1111 peer.read_to_end(&mut sent).unwrap();
1112 assert!(!sent.is_empty(), "the good emit reached the link");
1113 }
1114}