diff --git a/direct/src/dcparser/dcClass.cxx b/direct/src/dcparser/dcClass.cxx index 617f226361..6681fab54a 100644 --- a/direct/src/dcparser/dcClass.cxx +++ b/direct/src/dcparser/dcClass.cxx @@ -287,7 +287,9 @@ receive_update(PyObject *distobj, DatagramIterator &di) const { int field_id = packer.raw_unpack_uint16(); DCField *field = get_inherited_field(field_id); nassertv_always(field != NULL); + packer.begin_unpack(field); field->receive_update(packer, distobj); + packer.end_unpack(); di.skip_bytes(packer.get_num_unpacked_bytes()); } @@ -313,7 +315,11 @@ receive_update_broadcast_required(PyObject *distobj, DatagramIterator &di) const DCAtomicField *atom = field->as_atomic_field(); if (atom != (DCAtomicField *)NULL && atom->is_required() && atom->is_broadcast()) { + packer.begin_unpack(atom); atom->receive_update(packer, distobj); + if (!packer.end_unpack()) { + break; + } } } @@ -340,7 +346,11 @@ receive_update_all_required(PyObject *distobj, DatagramIterator &di) const { DCField *field = get_inherited_field(i); DCAtomicField *atom = field->as_atomic_field(); if (atom != (DCAtomicField *)NULL && atom->is_required()) { + packer.begin_unpack(atom); atom->receive_update(packer, distobj); + if (!packer.end_unpack()) { + break; + } } } @@ -379,7 +389,9 @@ direct_update(PyObject *distobj, const string &field_name, DCPacker packer; packer.set_unpack_data(value_blob); + packer.begin_unpack(field); field->receive_update(packer, distobj); + packer.end_unpack(); } #endif // HAVE_PYTHON @@ -504,9 +516,7 @@ client_format_update(const string &field_name, int do_id, return Datagram(); } - DCPacker packer; - field->client_format_update(packer, do_id, args); - return Datagram(packer.get_data(), packer.get_length()); + return field->client_format_update(do_id, args); } #endif // HAVE_PYTHON @@ -530,9 +540,7 @@ ai_format_update(const string &field_name, int do_id, return Datagram(); } - DCPacker packer; - field->ai_format_update(packer, do_id, to_id, from_id, args); - return Datagram(packer.get_data(), packer.get_length()); + return field->ai_format_update(do_id, to_id, from_id, args); } #endif // HAVE_PYTHON @@ -576,9 +584,11 @@ ai_format_generate(PyObject *distobj, int do_id, DCField *field = get_inherited_field(i); DCAtomicField *atom = field->as_atomic_field(); if (atom != (DCAtomicField *)NULL && atom->is_required()) { + packer.begin_pack(atom); if (!pack_required_field(packer, distobj, atom)) { return Datagram(); } + packer.end_pack(); } } @@ -601,9 +611,11 @@ ai_format_generate(PyObject *distobj, int do_id, return Datagram(); } + packer.begin_pack(field); if (!pack_required_field(packer, distobj, field)) { return Datagram(); } + packer.end_pack(); } } diff --git a/direct/src/dcparser/dcField.cxx b/direct/src/dcparser/dcField.cxx index 4c84abdf07..4ad82d6c67 100644 --- a/direct/src/dcparser/dcField.cxx +++ b/direct/src/dcparser/dcField.cxx @@ -186,13 +186,19 @@ validate_ranges(const string &packed_data) const { // Description: Packs the Python arguments from the indicated tuple // into the packer. Returns true on success, false on // failure. +// +// It is assumed that the packer is currently positioned +// on this field. //////////////////////////////////////////////////////////////////// bool DCField:: pack_args(DCPacker &packer, PyObject *sequence) const { + nassertr(!packer.had_error(), false); + nassertr(packer.get_current_field() == this, false); + nassertr(PySequence_Check(sequence), false); - packer.begin_pack(this); + packer.pack_object(sequence); - if (packer.end_pack()) { + if (!packer.had_error()) { /* PyObject *str = PyObject_Str(sequence); cerr << "pack " << get_name() << PyString_AsString(str) << "\n"; @@ -228,17 +234,19 @@ pack_args(DCPacker &packer, PyObject *sequence) const { // Access: Published // Description: Unpacks the values from the packer, beginning at // the current point in the unpack_buffer, into a Python -// tuple and returns the tuple. If there are remaining -// bytes in the unpack buffer, they are ignored (but the -// packer is left at the first unread byte). +// tuple and returns the tuple. +// +// It is assumed that the packer is currently positioned +// on this field. //////////////////////////////////////////////////////////////////// PyObject *DCField:: unpack_args(DCPacker &packer) const { - packer.begin_unpack(this); + nassertr(!packer.had_error(), NULL); + nassertr(packer.get_current_field() == this, NULL); PyObject *object = packer.unpack_object(); - if (packer.end_unpack()) { + if (!packer.had_error()) { // Successfully unpacked. /* PyObject *str = PyObject_Str(object); @@ -265,7 +273,8 @@ unpack_args(DCPacker &packer) const { */ nassert_raise(strm.str()); - return object; + Py_XDECREF(object); + return NULL; } #endif // HAVE_PYTHON @@ -281,16 +290,18 @@ void DCField:: receive_update(DCPacker &packer, PyObject *distobj) const { PyObject *args = unpack_args(packer); - if (PyObject_HasAttrString(distobj, (char *)_name.c_str())) { - PyObject *func = PyObject_GetAttrString(distobj, (char *)_name.c_str()); - nassertv(func != (PyObject *)NULL); - - PyObject *result = PyObject_CallObject(func, args); - Py_XDECREF(result); - Py_DECREF(func); + if (args != (PyObject *)NULL) { + if (PyObject_HasAttrString(distobj, (char *)_name.c_str())) { + PyObject *func = PyObject_GetAttrString(distobj, (char *)_name.c_str()); + nassertv(func != (PyObject *)NULL); + + PyObject *result = PyObject_CallObject(func, args); + Py_XDECREF(result); + Py_DECREF(func); + } + + Py_DECREF(args); } - - Py_DECREF(args); } #endif // HAVE_PYTHON @@ -302,12 +313,21 @@ receive_update(DCPacker &packer, PyObject *distobj) const { // to send an update for the indicated distributed // object from the client. //////////////////////////////////////////////////////////////////// -void DCField:: -client_format_update(DCPacker &packer, int do_id, PyObject *args) const { +Datagram DCField:: +client_format_update(int do_id, PyObject *args) const { + DCPacker packer; + packer.raw_pack_uint16(CLIENT_OBJECT_UPDATE_FIELD); packer.raw_pack_uint32(do_id); packer.raw_pack_uint16(_number); + + packer.begin_pack(this); pack_args(packer, args); + if (!packer.end_pack()) { + return Datagram(); + } + + return Datagram(packer.get_data(), packer.get_length()); } #endif // HAVE_PYTHON @@ -319,15 +339,24 @@ client_format_update(DCPacker &packer, int do_id, PyObject *args) const { // to send an update for the indicated distributed // object from the AI. //////////////////////////////////////////////////////////////////// -void DCField:: -ai_format_update(DCPacker &packer, int do_id, int to_id, int from_id, PyObject *args) const { +Datagram DCField:: +ai_format_update(int do_id, int to_id, int from_id, PyObject *args) const { + DCPacker packer; + packer.raw_pack_uint32(to_id); packer.raw_pack_uint32(from_id); packer.raw_pack_uint8('A'); packer.raw_pack_uint16(STATESERVER_OBJECT_UPDATE_FIELD); packer.raw_pack_uint32(do_id); packer.raw_pack_uint16(_number); + + packer.begin_pack(this); pack_args(packer, args); + if (!packer.end_pack()) { + return Datagram(); + } + + return Datagram(packer.get_data(), packer.get_length()); } #endif // HAVE_PYTHON diff --git a/direct/src/dcparser/dcField.h b/direct/src/dcparser/dcField.h index d4763ab40d..486105de1c 100644 --- a/direct/src/dcparser/dcField.h +++ b/direct/src/dcparser/dcField.h @@ -60,8 +60,9 @@ PUBLISHED: void receive_update(DCPacker &packer, PyObject *distobj) const; - void client_format_update(DCPacker &packer, int do_id, PyObject *args) const; - void ai_format_update(DCPacker &packer, int do_id, int to_id, int from_id, PyObject *args) const; + Datagram client_format_update(int do_id, PyObject *args) const; + Datagram ai_format_update(int do_id, int to_id, int from_id, + PyObject *args) const; #endif public: diff --git a/direct/src/dcparser/dcPacker.I b/direct/src/dcparser/dcPacker.I index e675bb73d9..83af1f5157 100755 --- a/direct/src/dcparser/dcPacker.I +++ b/direct/src/dcparser/dcPacker.I @@ -588,6 +588,20 @@ had_range_error() const { return _range_error; } +//////////////////////////////////////////////////////////////////// +// Function: DCPacker::had_error +// Access: Published +// Description: Returns true if there has been any error (either a +// pack error or a range error) since the most recent +// call to begin(). If this returns true, then the +// matching call to end() will indicate an error +// (false). +//////////////////////////////////////////////////////////////////// +INLINE bool DCPacker:: +had_error() const { + return _range_error || _pack_error; +} + //////////////////////////////////////////////////////////////////// // Function: DCPacker::get_num_unpacked_bytes // Access: Published diff --git a/direct/src/dcparser/dcPacker.cxx b/direct/src/dcparser/dcPacker.cxx index 7d58adc405..c6bd84ce63 100755 --- a/direct/src/dcparser/dcPacker.cxx +++ b/direct/src/dcparser/dcPacker.cxx @@ -104,7 +104,7 @@ end_pack() { clear(); - return !_pack_error && !_range_error; + return !had_error(); } //////////////////////////////////////////////////////////////////// @@ -205,7 +205,7 @@ end_unpack() { clear(); - return !_pack_error && !_range_error; + return !had_error(); } //////////////////////////////////////////////////////////////////// @@ -273,7 +273,7 @@ end_repack() { _mode = M_idle; clear(); - return !_pack_error && !_range_error; + return !had_error(); } //////////////////////////////////////////////////////////////////// diff --git a/direct/src/dcparser/dcPacker.h b/direct/src/dcparser/dcPacker.h index 8cb89a221f..12198f93b5 100755 --- a/direct/src/dcparser/dcPacker.h +++ b/direct/src/dcparser/dcPacker.h @@ -118,6 +118,7 @@ PUBLISHED: INLINE bool had_pack_error() const; INLINE bool had_range_error() const; + INLINE bool had_error() const; INLINE size_t get_num_unpacked_bytes() const; INLINE string get_string() const;